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# 言語仕様 $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# と同等にする唯一の F# の方法が属性であると仮定するとconst、 の右側で適切な型のリテラル列挙ケースを使用することになりますlet

于 2013-04-04T20:24:08.800 に答える
1

(MyEnum)0 この不一致は、C#は実際にはリテラルですが、F#enumは type の関数であるという事実によって引き起こされint32 -> 'Tます。
F# チームがこのコンストラクトに特別な処理を追加することは難しくないと思いますが、残念ながらまだ実装されていません。

それにもかかわらず、必要なことを達成するための 1 つの方法があり0ます。

type MyEnum =
    | None = 0
    | Foo = 1

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