7

这个 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 中修复,并按预期工作。

4

2 回答 2

2

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

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

  • 一个简单的常量表达式,除了 ()、本机整数文字、无符号本机整数文字、字节数组文字、BigInteger 文字和用户定义的数字文字。—或者—</li>
  • 对另一个字面量的引用

考虑

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.

于 2013-04-04T20:24:08.800 回答
1

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

尽管如此,有一种方法可以完成您的需要,但仅是为了0价值:

type MyEnum =
    | None = 0
    | Foo = 1

[<Literal>]
let X = MyEnum()
于 2013-01-25T23:39:27.587 回答