这个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
这种差异似乎很奇怪。
这已在v3.1中修复,并按预期工作。
答案 0 :(得分:2)
我认为观察到的编译器行为是有意的,完全符合F# Language Spec $10.2.2:
定义[<Literal>]
属性的值的限制
右侧表达式必须是 literal 常量表达式,它由以下两者组成:
- 一个简单的常量表达式,除了(),本机整数文字,无符号本机整数 文字,字节数组文字,BigInteger文字和用户定义的数字文字。 -OR -
- 对另一个文字的引用
考虑
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#方式,定义枚举文字值的唯一选择是在{{的右侧使用正确类型的文字枚举情况。 1}}。
答案 1 :(得分:1)
差异是由于C#(MyEnum)0
确实是文字,但F#enum
是int32 -> 'T
类型的函数。
我相信F#团队为这个构造添加特殊处理并不困难,但不幸的是它还没有。
尽管如此,有一种方法可以满足您的需求,但仅适用于0
值:
type MyEnum =
| None = 0
| Foo = 1
[<Literal>]
let X = MyEnum()