まず、あなたの混乱newはC++から来ていると思います。MyEnum e = MyEnum();そこでは、またはのようなものを書くことができますMyEnum* e = new MyEnum();。それぞれが異なることを意味します。C#にはそのような区別はなく、を使用して値を作成するかどうかは関係ありませnewん。
列挙型がスタックに格納されていることを読みました[…]。
それはひどく単純化しすぎているので、このように言うと間違っていると思います。Enumsはスタックに格納できますが、ヒープまたはレジスタに格納することもできます。そして、ほとんどの場合、それらが正確にどこに保存されているかは問題ではありません。
ただし、上記のコードスニペットでは、列挙型をインスタンス化します。このインスタンスはヒープに保存されますか?
上で言ったように、あなたが使用したかどうかは関係ありませんnew。保存される値が正確にどこにあるかは、状況によって異なります。
変数が実際に単純なローカルである場合:
let a = MyEnum.A
printfn "%A" a
次に、スタックまたはレジスタに格納されます。
ただし、同じ構文を使用して、次のタイプのフィールドを定義することもできます。
type Test() =
let a = MyEnum.A
member this.A
with get() = a
printfn "%A" (Test().A)
この場合、Testは参照型である.Netクラスであるaため、オブジェクトに割り当てられたメモリ内のヒープに格納されTestます。
しかし、あまり明白でないケースもあります。例えば:
let a = MyEnum.A
let getA() = a
printfn "%A" (getA())
この場合、のコードは直接返されるように最適化されるため、ローカルはどこaにも保存されません。getA()MyEnum.A
let a = (fun() -> MyEnum.A)()
let getA() = a
printfn "%A" (getA())
aより複雑な初期化を行うということは、以前の最適化が使用されずa、静的フィールドに格納されることを意味します(これらは通常、ヒープの特別なセクションに格納されます)。
したがって、ご覧のとおり、値が正確に格納される場所は非常に複雑で、コンパイラ固有の場合があります。そして、マイクロ最適化を実行しているのでない限り、それを気にする必要はありません。また、それは確かにとは何の関係もありませんnew。
トリックは機能しません:
typeof<MyEnum>.BaseType = typeof<System.ValueType>
…列挙型はSystem.Enum型であるため
しかし、Enumそれ自体はから派生してValueTypeいるので、これは次を返しますtrue:
typeof<MyEnum>.BaseType.BaseType = typeof<System.ValueType>
System.Enumとそれ自体が参照型であるという事実System.ValueTypeは、状況をさらに混乱させますが。