为什么这个嵌套对象初始化器抛出一个空引用异常?

时间:2015-06-03 12:58:03

标签: c# object-initializers

以下测试用例在尝试将Id分配给null的对象时抛出空引用异常,因为代码缺少" new R"在对象初始化程序之前。

为什么这不会被编译器捕获?为什么允许这样,用例会是一个有意义的构造吗?

[TestClass]
public class ThrowAway
{
    public class H
    {
        public int Id { get; set; }
    }

    public class R
    {
        public H Header { get; set; }
    }

    [TestMethod]
    public void ThrowsException()
    {
        var request = new R
                      {
                          Header =
                          {
                              Id = 1
                          },
                      };
    }
}

1 个答案:

答案 0 :(得分:18)

编译器不会发出警告,因为您可以:

public class R
{
    public H Header { get; set; }

    public R()
    {
        Header = new H();
    }
}

所以Header可以由某人/某事初始化。解决某人/某事物是否会初始化Header是一个复杂的问题(可能类似于暂停问题)...不是编译器想要为你解决的问题: - )

来自C#规范:

  

在等号后面指定对象初始值设定项的成员初始值设定项是嵌套对象初始值设定项,即嵌入对象的初始化。 嵌套对象初始值设定项中的赋值不是为字段或属性指定新值,而是将其视为对字段或属性成员的赋值。嵌套对象初始值设定项不能应用于具有值类型的属性,也不能应用于具有值类型的只读字段。

我们是嵌套初始化程序的情况,并看到粗体部分。我不知道。

现在,请注意,new R { }是C#规范,7.6.10.1 Object creation expressions后跟object-initializer,而Header = { }是“纯”7.6.10.2 Object initializers