为什么必须使用非默认构造函数初始化C#struct中的所有字段?

我想试试这段代码:

public struct Direction { private int _azimuth; public int Azimuth { get { return _azimuth; } set { _azimuth = value; } } public Direction(int azimuth) { Azimuth = azimuth } } 

但它在编译时失败,我理解struct需要初始化它的所有字段。 但我想了解在CLR \ IL引擎盖下发生了什么。 为什么它需要在任何其他方法\ property \ this等之前的所有字段

谢谢。

值类型是在堆栈上创建的(除非嵌套在引用类型中)堆栈上的字段/位置有一些东西,CLR无法保证它们将被清零(与托管堆上的字段/位置相反)保证被清零)。 因此,在阅读之前必须写入它们。 否则这是一个安全漏洞。

struct的默认ctor(不带参数,你不允许显式指定)将结构的所有字段清零,因此你可以使用结构。

 new BimonthlyPairStruct() 

但是,在实现参数化ctor时,必须确保已初始化所有字段 – 这是CLR将代码作为安全/ validation通过所必需的。

另见:CLR通过C#2nd Ed – Pg 188

这是因为结构派生自System.ValueType而不是System.Object,System.ValueType实现了您无法覆盖的默认构造函数,此默认构造函数使用其默认值初始化struct中的所有字段。 因此,如果要在类中实现任何参数构造函数,则还需要t0确保调用system.ValueType default const。 并且为了回答为什么需要初始化它的所有值,这是因为值存储在堆栈内存中。

这有效:

  public Direction(int azimuth) { _azimuth = azimuth; } 

从规格:

使用new运算符调用Struct构造函数,但这并不意味着正在分配内存。 结构构造函数只是返回结构值本身(通常在堆栈上的临时位置),而不是动态分配对象并返回对它的引用,然后根据需要复制该值。

基本上,编译器必须看到每个字段都在构造函数中初始化,以便它可以复制这些值,并且它不愿意检查对函数或属性的调用。

我刚刚在MSDN论坛中找到了一条说明,强制执行此规则,因为如果使用无默认构造函数,则会跳过清零内存。 因此,您必须为所有字段提供初始化值,以避免某些字段包含随机值。 您可以轻松地调用参数less default构造函数,但代价是初始化一些字段两次。

我不知道这个解释是否正确,但这听起来很合理。

当您定义非默认初始化程序时,C#要求您设置所有字段,因为它会跳过内存清零并允许您初始化它 – 否则您必须具有双初始化性能命中。 如果您不关心(非常轻微)性能命中,您始终可以将调用链接到:this()初始值设定项,然后仅初始化选定的字段。

 public struct Direction { public int Azimuth { get; private set; } public Direction(int azimuth) : this() { Azimuth = azimuth; } } 

您需要初始化字段,而不是通过属性。