C#值类型初始化之谜

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

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

但是在这篇文章中Jon Skeet说

为什么我不能在.NET中为结构定义默认构造函数?

“C#中的基本规则是”任何类型的默认值都不能依赖于任何初始化“意思如评论中所述。默认值始终是”你通过擦除内存得到的“。你不能提供任何显式实现,将始终被调用。

谁能告诉我谁是正确的?

当声明一个值类型时,实际发生了什么,它的构造函数被调用或内存被清除。

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

您似乎认为“任何类型的默认值都不能依赖于任何初始化”意味着“值类型不会被初始化” ,这是不正确的。 它们被初始化为0 。

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

当声明一个值类型时,实际发生了什么,它的构造函数被调用或内存被清除。

让我们说你有以下内容:

 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 

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

然后继续描述它们如何初始化:

initobj指令将推送地址(类型为native int,&或*)指定的值类型的每个字段初始化为空引用或适当原始类型的0 。 调用此方法后,实例已准备好调用构造函数方法。 如果typeTok是引用类型,则此指令与ldnull后跟stind.ref具有相同的效果。 与Newobj不同,initobj不会调用构造函数方法。 Initobj用于初始化值类型,而newobj用于分配和初始化对象。

所有这些实际上都certificate了值类型确实被初始化了(因为看起来您可能会质疑该语句)。

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

Mads Torgersen解释说 :

表达式’new Person()’将执行声明的构造函数,而不是提供默认值的标准行为。 但请注意,’default(Person)’仍然会产生默认值,每个数组元素的’new Person […]’也是如此。 在这些情况下,构造函数不会被执行:只有在结构类型上明确使用“new”时才会执行。

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

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

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