似乎对象初始值设定项与构造函数+属性赋值不同。怎么会这样?

时间:2017-11-18 12:39:19

标签: c#

请考虑以下代码:

class Data
{
    public string Name;
    public string NameWithSufix;
}

class Behaviour
{
    private Data data;
    public string Name { get { return data.Name; } private set { } }

    public Behaviour()
    {
        data = new Data()
        {
            Name = "My Name",
            NameWithSufix = Name + " Sufix",
        };
        //data = new Data();
        //data.Name = "My Name";
        //data.NameWithSufix = Name + " Sufix";
    }
}

class Program
{
    static void Main(string[] args)
    {
        Behaviour behaviour = new Behaviour();
    }
}

如果运行此程序,它将在Name属性中失败并显示NullReferenceException。 Thisthis回答和Visual Studio试图说服我对象初始化器和对象构造函数后跟属性赋值是相同的,但它似乎不是这样。如果我用注释代码交换构造函数的主体,它就可以工作。在尝试分配属性之前,似乎initiliazer实际上并没有运行构造函数。为什么呢?

2 个答案:

答案 0 :(得分:4)

Name中的{p> NameWithSufix = Name指向data.Name,当时data为空。对象初始化器的更好表示是:

Data d = new Data();
d.Name = "My Name";
d.NameWithSufix = this.data.Name /*Name*/ + " Sufix"; // <-- see the problem here

this.data = d;

在对象初始化程序完成之前,请注意this.data未设置。

如PetSerAl所述,C# language specification支持这一点。

答案 1 :(得分:3)

它首先运行Behavior构造函数。问题是Data类的初始化尚未完成,因此以下引用会引发异常

NameWithSufix = Name + " Sufix",

因为此时调用get { return data.Name; }data仍为null

更新

Patrick Hofman在他的回答中说得更好更准确 - 并不是Data类的初始化不完整,而是新实例尚未分配给{{1变量。

此外,he requested a clarification to the official docs - 如果您同意,请竖起大拇指。