开发者

Why does this C# assignment throw an exception?

开发者 https://www.devze.com 2023-03-16 12:38 出处:网络
public class A { private string _a_string; public string AString { get {开发者_JS百科 return _a_string; }
public class A
{
    private string _a_string;
    public string AString
    {
        get {开发者_JS百科 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; }
    }
}

This does not work:

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

System.NullReferenceException : Object reference not set to an instance of an object.

This works:

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

Both compile fine in VS2010.


The line

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

is equivalent to

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

I think in this form it's clear what's happening.

Compare this with the equivalent form of the expression that works:

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


There is no instantiation of A within B unless you explicitly instantiate it as in your second example.

Change to;

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

To use the first example.

In short, without the new A(), there is no A which is the cause of the NullReferenceException


In the first case, the code is effectively transformed by the compiler into

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

Since you never assigned b.A to an instance, you get the exception (specifically, since you never assigned b.A, a is null and thus a.AString is going to throw a NullReferenceException). The fact that nowhere is there code of the form new A... is a huge clue that an instance of A is never created.

You could solve this problem by adding A = new A() to the constructor of B, or adding a field initializer to B._a.

In the second case, the code is transformed by the compiler into

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

This is okay, because now we have an instance of A.


You can't use

A = { AString = "aString" }

because of the same reason you did

B _b = new B { 

you must declare an instance of B(and A) in order to use it.

If you would have written

B = B{...

you would get a similar error

0

精彩评论

暂无评论...
验证码 换一张
取 消