2011-06-29 78 views
7
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; } 
    } 
} 

这不起作用:为什么这个C#任务会抛出异常?

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

System.NullReferenceException:对象不设置到对象的实例。

这工作:

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

无论是在VS2010编译罚款。

+0

谢谢,@ryeguy –

回答

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(),没有这是NullReferenceException异常的原因

+0

谢谢 - 我知道如何得到它现在的工作,但我真的想了= {AString =“aString”}已经足够了。 –

5

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

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

相当于

我认为这种形式很清楚发生了什么事情。

与表达的等价形式的作品比较:

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

您可能是正确的,但我认为A = {AString =“aString”}会自行创建A的实例。我想我将不得不看IL才能真正发现...... –

+0

@OtávioDécio:它不会,因为编译器只是简单地将“简写”语法转换为长格式。但是要告诉你事实,如果你在一个小时前问过我,我不会认为这个问题表达是合法的C#。 – Jon

+0

虽然我修复了我的代码,但我认为这种行为足以导致一些混淆。猜想从现在开始初始化对象时我必须更加正统。 –

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一个实例。

+0

谢谢 - 但编写A = {AString =“aString”}时,编译器为什么不创建A的新实例? –

+1

因为你没有在任何地方使用'new A'。除非你告诉它,否则它不会创建实例。你通过使用'new'关键字来告诉它。 – jason

+0

因为在您的类或代码中没有显式实例化A.在你写A = {AString =“aString”}时,它不存在。 – ChrisBint

0

不能使用

A = { AString = "aString" } 

,因为你做了

B _b = new B { 

您必须声明B的一个实例(和A),才能使用它一样的道理。

如果你会写

B = B{... 

,你会得到一个类似的错误编辑

+0

@Reed - 如果我不行,那很好,但如果是这样的话 - 编译器为什么要这样做? –

+0

因为在编译时你还没有试图访问A,所以它会编译。编译器知道A是一个有效的类,但无法确定它是否已被实例化,因为这可能发生在其他地方。 – ChrisBint

+0

@Chris - 的确如此。 – Reed

相关问题