System.Enum类型的实例是否存储在堆上

时间:2013-01-27 15:43:34

标签: f# enums

考虑F#Enum声明:

type MyEnum =
  | A = 1
  | B = 2

我现在可以创建MyEnum类型的值:

let enumValue1 = MyEnum.A

推断值enumValue1的类型为MyEnum。

但是我也可以创建一个Enum类型的实例:

let enumValue2 = new MyEnum()

值enumValue2也是MyEnum类型。

我读到Enum类型是整数类型的包装,而Enum存储在堆栈中。

但是在上面的代码片段中,我实例化了我的Enum类型。这个实例存储在堆上?

本质上我很困惑Enums是存储在堆栈还是堆上(或者两者都可以根据情况而存在)?

诀窍不起作用:

typeof<MyEnum>.BaseType = typeof<System.ValueType> 

...因为Enums的类型为System.Enum

3 个答案:

答案 0 :(得分:1)

首先,我认为您对new的困惑来自C ++。在那里,您可以编写MyEnum e = MyEnum();MyEnum* e = new MyEnum();之类的内容,其中每个内容都有所不同。在C#中没有这样的区别,是否使用new创建值无关紧要。

  

我读到[...]枚举存储在堆栈中。

这是粗略的过度简化,我会说这是错的,当这样说时。 Enum可以存储在堆栈中,是的,但它们也可以存储在堆上或寄存器中。在大多数情况下,它们存储的确切位置并不重要。

  

但是在上面的代码片段中,我实例化了我的Enum类型。这个实例存储在堆上?

就像我上面说的那样,使用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。< / p>

let a = (fun() -> MyEnum.A)()

let getA() = a  

printfn "%A" (getA())

使a的初始化更复杂意味着不会使用先前的优化,并且a现在存储在静态字段中(那些通常存储在堆的特殊部分中)。


因此,正如您所看到的,存储值的确切位置可能非常复杂并且特定于编译器。除非你进行微观优化,否则你不应该关心它。此外,它肯定与new没有任何关系。

  

诀窍不起作用:

typeof<MyEnum>.BaseType = typeof<System.ValueType> 
     

...因为Enums的类型为System.Enum

Enum本身来自ValueType,因此返回true

typeof<MyEnum>.BaseType.BaseType = typeof<System.ValueType>

虽然System.EnumSystem.ValueType本身就是引用类型,但这种情况更令人困惑。

答案 1 :(得分:0)

.NET中的new关键字与C ++的new关键字(从堆中分配内存)不同。在.NET中,new只是创建一个对象的新实例并调用其构造函数(如果有的话)。新对象是在堆上还是堆栈上,通常取决于它是值类型还是引用类型,而不是您是否使用new

可以注意到int和其他原语也有0参数构造函数:

new Int16()

new或基本类型上使用Enum只会创建该类型的实例及其默认值(通常为0)。

答案 2 :(得分:0)

您可以将它们实例化为new MyEnum(),因为在.NET中,所有值类型都需要具有无参数的公共构造函数。对于枚举,这就像将0转换为枚举类型:

> LanguagePrimitives.EnumOfValue<_,MyEnum> 0;;
val it : MyEnum = 0

您还可以检查枚举是否实际上是值类型:

> typeof<MyEnum>.IsSubclassOf typeof<System.ValueType>;;
val it : bool = true