//CodeSample1
//declare class fileds but not initialize them.
public class Cat
{
public int Age;
public string Name;
}
Cat aCat = new Cat();
检查结果, aCat.Age为0,aCat.Name为空。
如何初始化字段?上面的代码只是声明字段而不是初始化它们。
如果没有为对象提供构造函数,C#将默认创建一个实例化对象并将成员变量设置为默认值表中列出的默认值。(来自{{ 3}})
所以这是编译器生成的默认构造函数初始化字段。是不是?
更改了代码,在声明时初始化字段。
//CodeSample2
//declare class fields and initialize them at same time.
public class Cat
{
public int Age = 4;
public string Name = "Black";
}
Cat aCat = new Cat();
这次结果是 aCat.Age为4,aCat.Name为“Black”。
我知道结果符合预期。但是不明白它是如何工作的。
字段在调用对象实例的构造函数之前立即初始化。(来自Microsoft document 1)
组合Microsoft Document 2和the Microsoft document 1,CodeSample1和CodeSample2应该有相同的结果(我知道这很奇怪)。
我的理解是,在CodeSample2中,首先将Age字段初始化为4,然后调用编译器生成的默认构造函数并将age设置为默认值(0)。
我是否误解了这些文件,或者文件有些不对?
如果有更准确的文件,请告诉我。
答案 0 :(得分:2)
您正在使用C#编程指南。不幸的是,有时它试图简化事情,在这种情况下,我会说它所做的简化导致了文档中的错误。
相反,如果我们咨询C# language specification(目前,版本5是最新版本。可以在Github找到6的草稿),我们会获得更权威的版本。首先,让我们看看默认构造函数,在10.11.4节中:
如果类不包含实例构造函数声明,则会自动提供默认实例构造函数。该默认构造函数只是调用直接基类的无参数构造函数。如果类是抽象的,那么默认构造函数的声明可访问性将受到保护。否则,默认构造函数的声明可访问性是公共的。因此,默认构造函数始终为
形式protected C(): base() {}
或
public C(): base() {}
因此,正如我们已经看到的那样 - 没有声明这里关于初始化字段。现在,我们来看看10.5.4节,字段初始化:
字段的初始值(无论是静态字段还是实例字段)是字段类型的默认值(第5.2节)。在发生此默认初始化之前,无法观察字段的值,因此字段永远不会“未初始化”。
好的,所以字段始终使用其类型的默认值进行初始化,无论发生什么。这总是先发生。最后,10.5.5,变量初始化说明了这一点:
§10.5.4中描述的默认值初始化适用于所有字段,包括具有变量初始值设定项的字段...当创建类的实例时,该实例中的所有实例字段首先初始化为其默认值,然后按文本顺序执行实例字段初始值设定项。
和
类的实例字段变量初始值设定项对应于在进入该类的任何一个实例构造函数(第10.11.1节)后立即执行的赋值序列