为什么这个C#赋值会抛出异常

本文关键字:抛出异常 赋值 为什么 | 更新日期: 2023-09-27 18:00:47

public class A
{
    private string _a_string;
    public string AString
    {
        get { return _a_string; }
        set {  _a_string = value; }
    }
}
public class B
{
    private string _b_string;
    private A _a;
    public A A
    {
        get { return _a; }
        set { _a = value; }
    }
    public string BString
    {
        get { return _b_string;  }
        set { _b_string = value; }
    }
}

这不起作用:

    B _b = new B { A = { AString = "aString" }, BString = "bString" };

系统。NullReferenceException:对象引用未设置为对象的实例

这项工作:

    B _b = new B { A = new A { AString = "aString" }, BString = "bString" };

两者都在VS2010中编译良好。

为什么这个C#赋值会抛出异常

B _b = new B { A = { AString = "aString" }, BString = "bString" };

相当于

B _b = new B();
_b.A.AString = "aString"; // null reference here: _b.A == null
_b.BString = "bString";

我认为在这种形式下,发生的事情很清楚。

将其与有效的等效表达式形式进行比较:

B _b = new B();
_b.A = new A();
_b.A.AString = "aString"; // just fine now
_b.BString = "bString";

除非像第二个例子中那样显式实例化,否则B中没有A的实例化。

更改为;

public class B
{
    private string _b_string;
    private A _a = new A();
    public A A
    {
        get { return _a; }
        set { _a = value; }
    }
    public string BString
    {
        get { return _b_string;  }
        set { _b_string = value; }
    }
}

使用第一个示例。

简而言之,如果没有新的A((,就没有A这是导致NullReferenceException

的原因

在第一种情况下,编译器将代码有效地转换为

B b = new B();
A a = b.A;
a.AString = "aString";
b.BString = "bString";

由于从未将b.A分配给实例,因此会得到异常(特别是,由于从未分配b.Aa为null,因此a.AString将抛出NullReferenceException(没有new A...形式的代码这一事实是一个巨大的线索,表明从未创建过A的实例

可以通过将A = new A()添加到B的构造函数中,或者向B._a添加字段初始值设定项来解决此问题。

在第二种情况下,编译器将代码转换为

B b = new B();
A a = new A();
a.AString = "aString";    
b.A = a;
b.BString = "bString";

这没关系,因为现在我们有了A的一个实例。

您不能使用

A = { AString = "aString" }

因为和你做的原因一样

B _b = new B { 

您必须声明B(和A(的实例才能使用它。

如果你会写

B = B{...

您会得到类似的错误