为什么这个嵌套对象初始值设定项会抛出空引用异常?

Why does this nested object initializer throw a null reference exception?

以下测试用例在尝试将 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
                          },
                      };
    }
}

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

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

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

所以 Header 可以被 someone/something 初始化。解决 if someone/something will initialize Header 是一个复杂的问题(可能类似于停止问题)...不是编译器想要为您解决的问题:-)

来自 C# 规范:

A member initializer that specifies an object initializer after the equals sign is a nested object initializer, i.e. an initialization of an embedded object. Instead of assigning a new value to the field or property, the assignments in the nested object initializer are treated as assignments to members of the field or property. Nested object initializers cannot be applied to properties with a value type, or to read-only fields with a value type.

我们在嵌套初始化器的情况下,看到粗体部分。我不知道。

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