繁体   English   中英

对象初始化期间的 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
                }
            };
    }
}

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

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

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

正如您所指出的,这将起作用:

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

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

    public _B B = new A._B();

为什么它在没有 new 的情况下编译良好,然后在运行时失败?

编译器需要做太多的工作来挖掘A类的代码并意识到此时B肯定会为空:正如我指出的那样,您可以更改A的构造函数的实现以确保这是不是这样。 这就是空引用异常是最常见的异常类型的原因之一。

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

2021 年更新

现在 C# 支持可为空的引用类型,您可以使用它来鼓励/强制程序员知道您的字段可能为空,如果这是您想要采取的路线。

    public _B? B;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM