2

考虑一个 F# 枚举声明:

type MyEnum =
  | A = 1
  | B = 2

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

let enumValue1 = MyEnum.A

值 enumValue1 被推断为 MyEnum 类型。

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

let enumValue2 = new MyEnum()

值 enumValue2 也是 MyEnum 类型。

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

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

从本质上讲,我很困惑枚举是存储在堆栈还是堆上(或者两者都取决于情况)?

这个技巧不起作用:

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

...因为枚举是 System.Enum 类型

4

3 回答 3

1

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

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

那是过于简单化了,当这样说时,我会说这是错误的。Enums 可以存储在堆栈中,是的,但它们也可以存储在堆或寄存器中。在大多数情况下,它们的确切存储位置对您来说并不重要。

但是在上面的代码片段中,我实例化了我的 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直接返回。

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.EnumSystem.ValueType它们本身是引用类型这一事实使情况更加混乱。

于 2013-01-27T21:59:18.653 回答
0

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

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

new Int16()

new在一个或一个原始类型上使用Enum只会创建一个具有默认值(通常为 0)的该类型的实例。

于 2013-01-27T15:56:26.163 回答
0

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

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

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

> typeof<MyEnum>.IsSubclassOf typeof<System.ValueType>;;
val it : bool = true
于 2013-01-27T15:56:32.983 回答