对象初始化期间的NullReferenceException

时间:2015-10-21 17:14:40

标签: c# nullreferenceexception

为什么尝试在下面的代码中设置X的值时会出现NullReferenceException?我在初始化new时使用B关键字时工作正常,但是为什么它在没有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
                }
            };
    }
}

1 个答案:

答案 0 :(得分:4)

初始化语法可能很棘手。在您的代码中,您首先尝试设置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 class A
{
    public _B B = new A._B();
    public class _B
    {
        public int X;
    }
}
  

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

编译器需要花费太多工作来深入研究A类的代码,并意识到此时B肯定会为空:正如我所说,你可以改变A的构造函数的实现,以确保不是这种情况。这是空引用异常是最常见的异常类型的一个原因。

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