如何使用基础值定义一个枚举常量

什么是这个C#的F#等价物:

const MyEnum None = (MyEnum)1;

这不起作用:

[<Literal>]
let None : MyEnum = enum 1 //ERROR: not a valid constant expression

尽管奇怪的是,在一个属性构造函数中没关系:

[<MyAttribute(enum 1)>]
type T = class end

这种差异似乎很奇怪。

UPDATE

这已在v3.1中修复,并按预期工作。


我相信观察到的编译器行为是有意的,并且完全符合由F#Language Spec $ 10.2.2定义的具有[<Literal>]属性值的限制:

右侧表达式必须是由以下任一项组成的文字常量表达式:

  • 一个简单的常量表达式,除了(),本地整型文本,无符号本地整型文本,字节型数组文本,BigInteger文本和用户定义的数字文本之外。 -要么-
  • 对另一个文字的引用
  • 考虑

    type MyEnum =
    | Case1 = 1
    | Case2 = 2
    

    然后

    [<Literal>]
    let Valid: MyEnum = MyEnum.Case1 // Literal enumeration case on the right
    

    会愉快地编译,但是

    [<Literal>]
    let Invalid: MyEnum = enum<MyEnum>(1) // Expression on the right
                                          // generating constant value, which
                                          // potentially might be completely off
                                          // legit MyEnum cases
    

    不会,虽然在[<Literal>]上下文中,两个语句都会编译成完全相同的IL。

    假设[<Literal>]属性是使C# const等价的唯一F#方法,定义枚举文字值的唯一选择是使用let右侧的正确类型的文字枚举大小写。


    这种差异是由C# (MyEnum)0确实是一个文字,但F# enum是类型为int32 -> 'T的函数引起的。
    我相信F#团队为这个构造添加特殊处理并不困难,但不幸的是它还没有。

    尽管如此,有一种方法可以实现你所需要的,但只有0值:

    type MyEnum =
        | None = 0
        | Foo = 1
    
    [<Literal>]
    let X = MyEnum()
    
    链接地址: http://www.djcxy.com/p/11761.html

    上一篇: How to define an enum constant using the underlying value

    下一篇: Repeating Decimal Algorithm