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

Hug*_*ist 17 c# object-initializers

以下测试用例在尝试将Id分配给空的对象时抛出空引用异常,因为代码在对象初始值设定项之前缺少"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
                          },
                      };
    }
}
Run Code Online (Sandbox Code Playgroud)

xan*_*tos 18

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

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

    public R()
    {
        Header = new H();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

从C#规范:

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

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

现在,请注意new R { },通过C#规范,7.6.10.1 Object creation expressions后跟一个object-initializer,而这Header = { }是一个"纯粹" 7.6.10.2 Object initializers.