简体   繁体   English

对象初始化期间的 NullReferenceException

[英]NullReferenceException during object initialization

Why there's a NullReferenceException when trying to set value of X in the code below?为什么在下面的代码中尝试设置 X 的值时会出现 NullReferenceException? It works fine when I use new keyword when initializing B , but why it compiles fine without new and then fails during runtime?当我在初始化B时使用new关键字时它工作正常,但是为什么它在没有new情况下编译良好,然后在运行时失败?

https://dotnetfiddle.net/YNvPog 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
                }
            };
    }
}

Initialization syntax can be tricky.初始化语法可能很棘手。 In your code, you're trying to set the value of aBX without first setting the value of B .在您的代码中,您尝试设置aBX的值而不先设置B的值。 Your code translates to:您的代码转换为:

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

... which would produce the same exception you're getting now. ...这会产生与您现在相同的异常。 That's because aB is initialized to null unless you explicitly create an instance for it.那是因为aB被初始化为null除非你明确地为它创建一个实例。

As you noted, this will work:正如您所指出的,这将起作用:

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

You could also make sure that A 's constructor initializes a B .您还可以确保A的构造函数初始化B

    public _B B = new A._B();

why it compiles fine without new and then fails during runtime?为什么它在没有 new 的情况下编译良好,然后在运行时失败?

It would require too much work for the compiler to dig into the code for your A class and realize that B will definitely be null at this point in time: as I pointed out you could change the implementation of A 's constructor to make sure that's not the case.编译器需要做太多的工作来挖掘A类的代码并意识到此时B肯定会为空:正如我指出的那样,您可以更改A的构造函数的实现以确保这是不是这样。 This is one reason that null reference exceptions are the most common type of exception out there.这就是空引用异常是最常见的异常类型的原因之一。

The best strategy to avoid this is to initialize all of your fields to non-null values in the constructor.避免这种情况的最佳策略是在构造函数中将所有字段初始化为非空值。 If you won't know what value to give them until your constructor is invoked, then make your constructor take those values as parameters.如果在调用构造函数之前您不知道要赋予它们什么值,那么让构造函数将这些值作为参数。 If you expect one of your fields may not always have a value, you can use an optional type like my Maybe<> struct to force programmers to deal with that fact at compile-time.如果您希望您的某个字段可能并不总是有值,您可以使用像我的Maybe<>结构这样的可选类型来强制程序员在编译时处理这个事实。

Update 2021 2021 年更新

Now C# supports nullable reference types , which you can use to encourage/force programmers to know that your field could be null, if that's the route you want to take.现在 C# 支持可为空的引用类型,您可以使用它来鼓励/强制程序员知道您的字段可能为空,如果这是您想要采取的路线。

    public _B? B;

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

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