C#值类型初始化之谜

时间:2015-01-19 12:03:27

标签: c# .net

http://msdn.microsoft.com/en-us/library/s1ax56ch.aspx

在上面提到的文章中我读过。 " 每个值类型都有一个隐式默认构造函数,用于初始化该类型的默认值。"

但在本文中,Jon Skeet说

Why can't I define a default constructor for a struct in .NET?

" C#中的基本规则是"任何类型的默认值都不能依赖于任何初始化" 意思是评论中提到的。  默认值始终是"您通过擦除内存"获得的内容。您无法提供任何始终被调用的显式实现。

有人能告诉我谁是正确的吗?

当声明值类型时,实际发生的事情是调用其构造函数或擦除内存。

3 个答案:

答案 0 :(得分:3)

  

当声明其构造函数的值类型时实际发生的事情   被叫或记忆被消灭了。

假设您有以下内容:

public struct Foo
{
    public int A { get; set; }
    public object B { get; set; }
}

并分配Foo

var f = new Foo();

编译器发出对initobj的调用:

IL_0001:  ldloca.s    00 // f
IL_0003:  initobj     UserQuery.Foo
  

将指定地址的值类型的每个字段初始化为a   null引用或适当原始类型的0

继续描述 如何初始化:

  

initobj指令初始化值类型的每个字段   由推送的地址(类型为native int,&或*)指定为a    null引用或0 的相应基元类型。在这之后   调用方法,实例已准备好构造函数方法   调用。如果typeTok是引用类型,则此指令具有相同的名称   效果为ldnull,后跟stind.ref。与Newobj不同,initobj确实如此   不要调用构造函数方法。 Initobj用于初始化   值类型,而newobj用于分配和初始化对象。

所有这些实际上都证明了值类型被初始化的事实(因为看起来您可能会质疑该陈述)。

请注意,从 C#6.0 开始,您可以为值类型声明默认的无参数构造函数。如果这样做,如果您通过new运算符显式实例化您的值类型,则会调用它。

Mads Torgersen explains

  

表达式'new Person()'将执行声明的构造函数   而不是提供默认值的标准行为。注意,   但是,'default(Person)'仍会产生默认值,   和每个数组元素的'new Person [...]'一样。在那些情况下   构造函数未执行:仅在您明确使用时才执行   结构类型的'new'。

对于所有托管CLR类型(垃圾收集器),擦除它的人都是一样的。它会注意到它不再被指向,并将收集类型并发挥其魔力。

答案 1 :(得分:2)

两个链接都不相互矛盾。如果你能解释为什么这么认为会有所帮助。

您似乎认为"任何类型的默认值都不能依赖于任何初始化" 意味着"值类型不是" t初始化" ,这不是真的。 They get initialized to 0

Jon的意思是说(并且确实如此)"用户无法为价值类型提供自定义构造函数"

答案 2 :(得分:0)

这根本不是什么神秘的事。使用隐式默认构造函数初始化所有值类型,该构造函数负责为类型分配默认值。实际上,这是一个显示每种值类型的默认值的链接。

https://msdn.microsoft.com/en-us/library/83fhsxwc.aspx