对象初始化期间出现 NullReferenceException

2024-01-19

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

初始化语法可能很棘手。在您的代码中,您尝试设置的值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();

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

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

避免这种情况的最佳策略是在构造函数中将所有字段初始化为非空值。如果在调用构造函数之前您不知道要给它们什么值,那么请让构造函数将这些值作为参数。如果您预计某个字段可能并不总是有值,则可以使用可选类型like my Maybe<> struct https://github.com/j2jensen/CallMeMaybe迫使程序员在编译时处理这个事实。

2021 年更新

现在C#支持可为空的引用类型 https://learn.microsoft.com/en-us/dotnet/csharp/nullable-references,您可以使用它来鼓励/强制程序员知道您的字段可能为空(如果这是您想要采取的路线)。

    public _B? B;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

对象初始化期间出现 NullReferenceException 的相关文章

随机推荐