まず、あなたの混乱new
はC++から来ていると思います。MyEnum e = MyEnum();
そこでは、またはのようなものを書くことができますMyEnum* e = new MyEnum();
。それぞれが異なることを意味します。C#にはそのような区別はなく、を使用して値を作成するかどうかは関係ありませnew
ん。
列挙型がスタックに格納されていることを読みました[…]。
それはひどく単純化しすぎているので、このように言うと間違っていると思います。Enum
sはスタックに格納できますが、ヒープまたはレジスタに格納することもできます。そして、ほとんどの場合、それらが正確にどこに保存されているかは問題ではありません。
ただし、上記のコードスニペットでは、列挙型をインスタンス化します。このインスタンスはヒープに保存されますか?
上で言ったように、あなたが使用したかどうかは関係ありません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
は、状況をさらに混乱させますが。