1

使用下面的代码,成功和失败被编译成 2 个独立的类。如何为成功和失败提供自定义属性?

type Result<'TSuccess,'TFailure> = 
    | Success of 'TSuccess
    | Failure of 'TFailure

编辑 因为SuccessFailure导致类我需要用类兼容属性来装饰它们AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Interface)

我可以让它工作吗?如果不是,为什么不呢?

[<ClassAttribute>]
type Result<'TSuccess,'TFailure> = 
    | [<ClassAttribute>] Success of 'TSuccess
    | [<ClassAttribute>] Failure of 'TFailure
4

2 回答 2

3

New<Case>联合案例的属性与返回该案例的子类的静态方法相关联,或者与Case无价值案例的属性相关联。在 F# 中使用此定义...

type Result<'TSuccess,'TFailure> = 
    | [<Obsolete>] Success of 'TSuccess
    | Failure of 'TFailure
    | [<Obsolete>] NotSure

使用这个 C# 片段来调用反编译...

var y = Result<string, string>.NewSuccess("yay");
var z = Result<string, string>.NotSure;

转到 NewSuccess 的定义将调出 Result 的 C# 定义,from metadata显示过时的属性。

[Obsolete]
public static Result<TSuccess, TFailure> NewSuccess(TSuccess item);

[Serializable]
[DebuggerDisplay("{__DebugDisplay(),nq}")]
public class Success : Result<TSuccess, TFailure>
{
  [CompilationMapping(SourceConstructFlags.Field, 0, 0)]
  [CompilerGenerated]
  [DebuggerNonUserCode]
  public TSuccess Item { get; }
}

对于像上面的 NotSure 这样没有值的案例标识符,案例成为属性而不是子类,并且附加到案例的过时属性在元数据反编译过程中被编译成稀薄的空气......

[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[DebuggerNonUserCode]
public static Result<TSuccess, TFailure> NotSure { get; }

通过ILdasm查看,两者的属性都很好......

Method #3 (06000003) 
-------------------------------------------------------
MethodName: NewSuccess (06000003)
Flags     : [Public] [Static] [ReuseSlot]  (00000016)
RVA       : 0x00002064
ImplFlags : [IL] [Managed]  (00000000)
CallCnvntn: [DEFAULT]
ReturnType: GenericInst Class Result`2< Var!0, Var!1>
1 Arguments
    Argument #1:  Var!0
1 Parameters
    (1) ParamToken : (08000001) Name : item flags: [none] (00000000)
CustomAttribute #1 (0c000011)
-------------------------------------------------------
    CustomAttribute Type: 0a00000b
    CustomAttributeName: System.ObsoleteAttribute :: instance void .ctor()
    Length: 4
    Value : 01 00 00 00                                      >                <
    ctor args: ()

CustomAttribute #2 (0c000012)
-------------------------------------------------------
    CustomAttribute Type: 0a00000c
    CustomAttributeName: Microsoft.FSharp.Core.CompilationMappingAttribute :: instance void .ctor(value class Microsoft.FSharp.Core.SourceConstructFlags,int32)
    Length: 12
    Value : 01 00 08 00 00 00 00 00  00 00 00 00             >                <
    ctor args: ( <can not decode> )


Method #7 (06000007) 
-------------------------------------------------------
MethodName: get_NotSure (06000007)
Flags     : [Public] [Static] [ReuseSlot]  (00000016)
RVA       : 0x0000208c
ImplFlags : [IL] [Managed]  (00000000)
CallCnvntn: [DEFAULT]
ReturnType: GenericInst Class Result`2< Var!0, Var!1>
No arguments.
CustomAttribute #1 (0c000030)
-------------------------------------------------------
    CustomAttribute Type: 0a00000b
    CustomAttributeName: System.ObsoleteAttribute :: instance void .ctor()
    Length: 4
    Value : 01 00 00 00                                      >                <
    ctor args: ()

CustomAttribute #2 (0c000031)
-------------------------------------------------------
    CustomAttribute Type: 0a00000c
    CustomAttributeName: Microsoft.FSharp.Core.CompilationMappingAttribute :: instance void .ctor(value class Microsoft.FSharp.Core.SourceConstructFlags,int32)
    Length: 12
    Value : 01 00 08 00 00 00 02 00  00 00 00 00             >                <
    ctor args: ( <can not decode> )
于 2014-09-16T22:18:04.290 回答
2

属性可以放在|并集的名称和名称之间。

这是一个简单的例子

open System
type t =  |[<Obsolete("hello")>]A
于 2014-07-31T00:24:34.167 回答