How to define an enum constant using the underlying value

What is the F# equivalent of this C#:

const MyEnum None = (MyEnum)1;

This does not work:

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

although, curiously, it's okay in an attribute constructor:

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

The discrepancy seems odd.

UPDATE

This is fixed in v3.1 and works as expected.


I believe the observed compiler behavior is intentional and completely in line with restrictions for values having [<Literal>] attribute defined by F# Language Spec $10.2.2:

The right-hand side expression must be a literal constant expression that is made up of either:

  • A simple constant expression, with the exception of (), native integer literals, unsigned native integer literals, byte array literals, BigInteger literals , and user-defined numeric literals. —OR—
  • A reference to another literal
  • Consider

    type MyEnum =
    | Case1 = 1
    | Case2 = 2
    

    then

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

    will happily compile, but

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

    will not, although outside of [<Literal>] context both statements will compile into absolutely identical IL.

    Assuming that [<Literal>] attribute is the only F# way of making C# const equivalent the only option for defining enumeration literal value would be using a literal enumeration case of proper type on the right side of let .


    The discrepancy is caused by the fact that C# (MyEnum)0 is indeed a literal, but F# enum is a function of type int32 -> 'T .
    I believe it would not be difficult for F# team to add special processing for this construct, but unfortunately it is not there yet.

    Nevertheless, there is one way to accomplish what you need, but only for 0 value:

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

    上一篇: ComboBox SelectionChangeCommitted事件不适用于AutoComplete

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