对象初始化期间出现 NullReferenceException

NullReferenceException during object initialization

为什么尝试在下面的代码中设置 X 的值时出现 NullReferenceException?当我在初始化 B 时使用 new 关键字时它工作正常,但为什么它在没有 new 的情况下编译正常然后在运行时失败?

https://dotnetfiddle.net/YNvPog

public class A
{
    public _B B;
    public class _B
    {
        public int X;
    }
}

public class Program
{
    public static void Main()
    {
        var a=new A{
                B={
                    X=1
                }
            };
    }
}

初始化语法可能很棘手。在您的代码中,您尝试设置 a.B.X 的值而不先设置 B 的值。您的代码转换为:

var a = new A();
a.B.X = 1;

... 这会产生与您现在遇到的相同的异常。那是因为 a.B 被初始化为 null 除非你明确地为它创建一个实例。

如您所述,这将起作用:

    var a=new A{
            B= new _B {
                X=1
            }
        };

您还可以确保 A 的构造函数初始化 B.

    public _B B = new A._B();

why it compiles fine without new and then fails during runtime?

编译器需要做太多工作才能深入研究您的 A class 的代码并意识到 B 此时肯定为 null:如我指出您可以更改 A 的构造函数的实现以确保不是这种情况。这是空引用异常是最常见的异常类型的原因之一。

避免这种情况的最佳策略是在构造函数中将所有字段初始化为非空值。如果在调用构造函数之前不知道要赋予它们什么值,则让构造函数将这些值作为参数。如果您希望您的某个字段可能不总是有值,您可以使用可选类型 like my Maybe<> struct 强制程序员在编译时处理该事实。

2021 年更新

现在 C# 支持 nullable reference types,您可以使用它来让 encourage/force 程序员知道您的字段可以为空,如果这是您想要采用的路线。

    public _B? B;