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

时间:2011-06-29 19:13:51

标签: c#

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" };

System.NullReferenceException:对象引用未设置为对象的实例。

这有效:

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

在VS2010中编译都很好。

4 个答案:

答案 0 :(得分:6)

该行

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";

答案 1 :(得分:4)

除非你在第二个例子中明确地实例化它,否则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的原因

答案 2 :(得分:1)

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

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

由于您从未将b.A分配给实例,因此您获得了异常(具体而言,由于您从未分配b.A,因此a为空,因此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的实例。

答案 3 :(得分:0)

你不能使用

A = { AString = "aString" }

因为你做了同样的原因

B _b = new B { 

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

如果你想写的话

B = B{...

你会得到类似的错误