2015-06-03 51 views
17

由於代碼在對象初始值設定項之前缺少「new R」,因此以下測試用例在嘗試將Id分配給空對象時會拋出空引用異常。爲什麼這個嵌套對象初始值設定項會拋出一個空引用異常?

爲什麼這不被編譯器捕獲?爲什麼它是允許的,哪些用例會成爲一個有意義的構造?

[TestClass] 
public class ThrowAway 
{ 
    public class H 
    { 
     public int Id { get; set; } 
    } 

    public class R 
    { 
     public H Header { get; set; } 
    } 

    [TestMethod] 
    public void ThrowsException() 
    { 
     var request = new R 
         { 
          Header = 
          { 
           Id = 1 
          }, 
         }; 
    } 
} 
+0

您必須初始化R對象的Header屬性。 'var request = new R {Header = new H {Id = 1}};' – Styxxy

+3

非常有趣的問題......它甚至不清楚編譯器是在做一個演員還是什麼...... – xanatos

+3

非常有趣的問題,但在我看來,這個標題非常差。你會考慮將它改爲你所問的實際問題嗎? – julealgon

回答

18

編譯器不會發出警告,因爲你可以有:

public class R 
{ 
    public H Header { get; set; } 

    public R() 
    { 
     Header = new H(); 
    } 
} 

所以Header可能是因爲有人/東西被初始化。解決如果某人/某事會初始化Header是一個複雜的問題(可能類似於停機問題)......不是一個編譯器要爲您解決:-)

從C#規格:

成員初始值設定項在等號之後指定對象初始值設定項是嵌套對象初始值設定項,即嵌入對象的初始化。 而不是分配一個新的值到字段或屬性,嵌套的對象初始值設定項中的分配被視爲字段或屬性成員的分配。嵌套對象初始值設定項不能應用於具有值類型的屬性,也不能應用於具有值類型的只讀字段。

我們在嵌套初始化器的情況下,看到粗體部分。我不知道。

現在,請注意new R { },通過C#規範,一個7.6.10.1 Object creation expressions後跟object-initializer,而Header = { }是一個 「純」 7.6.10.2 Object initializers

+1

同樣的問題,在這裏的另一個帖子 - 爲什麼它允許'頭= {Id = 1}'?無論如何,這看起來是錯的,不是嗎? – Andrei

+0

@Andrei至少我解釋了*爲什麼沒有被編譯器捕獲?* :-) – xanatos

+0

對不起,我還是不明白。不想爭辯,只是很好奇自己。編譯器應該在這樣的語法上失敗了,不管在ctor中是否有初始化,對吧? – Andrei

相關問題