Fra*_*nta 2 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
}
};
}
}
Run Code Online (Sandbox Code Playgroud)
初始化语法可能很棘手。在您的代码中,您尝试设置 的值a.B.X而不先设置 的值B。您的代码转换为:
var a = new A();
a.B.X = 1;
Run Code Online (Sandbox Code Playgroud)
...这会产生与您现在相同的异常。那是因为除非您明确为它创建一个实例,否则它会a.B被初始化null为。
正如您所指出的,这将起作用:
var a=new A{
B= new _B {
X=1
}
};
Run Code Online (Sandbox Code Playgroud)
您还可以确保 thatA的构造函数初始化 a B。
public _B B = new A._B();
Run Code Online (Sandbox Code Playgroud)
为什么它在没有 new 的情况下编译良好,然后在运行时失败?
编译器需要做太多的工作来挖掘您的A类的代码并意识到此时B肯定会为空:正如我指出的那样,您可以更改A的构造函数的实现以确保情况并非如此. 这是空引用异常是最常见的异常类型的原因之一。
避免这种情况的最佳策略是在构造函数中将所有字段初始化为非空值。如果在调用构造函数之前您不知道要赋予它们什么值,那么让构造函数将这些值作为参数。如果您希望您的某个字段可能并不总是有值,您可以使用像 my Maybe<>struct这样的可选类型来强制程序员在编译时处理这个事实。
现在 C# 支持可为空的引用类型,您可以使用它来鼓励/强制程序员知道您的字段可能为空,如果这是您想要采取的路线。
public _B? B;
Run Code Online (Sandbox Code Playgroud)