2015-09-01 79 views
20
using System; 
using System.Collections.Generic; 

class Parent 
{ 
    public Child Child { get; set; } 
} 

class Child 
{ 
    public List<string> Strings { get; set; } 
} 

static class Program 
{ 
    static void Main() { 
     // bad object initialization 
     var parent = new Parent() { 
     Child = { 
      Strings = { "hello", "world" } 
     } 
     }; 
    } 
} 

上述程序編譯罰款,但在運行時與對象引用未設置到對象的實例崩潰。沒有「新目錄」初始化列表屬性引起的NullReferenceException

如果你注意到上面的代碼片段,我有在初始化子屬性時省略了新的

顯然初始化正確的做法是:

 var parent = new Parent() { 
     Child = new Child() { 
      Strings = new List<string> { "hello", "world" } 
     } 
     }; 

我的問題是,爲什麼C#編譯器不會當它看到第一個構建抱怨嗎?

爲什麼壞了初始化有效語法?

 var parent = new Parent() { 
     Child = { 
      Strings = { "hello", "world" } 
     } 
     }; 

回答

4

第二語法是有效的只讀屬性。如果更改代碼以在相應的構造函數中初始化Child和Strings屬性,則語法將起作用。

class Parent 
{ 
    public Parent() 
    { 
     Child = new Child(); 
    } 

    public Child Child { get; private set; } 
} 

class Child 
{ 
    public Child() 
    { 
     Strings = new List<string>(); 
    } 
    public List<string> Strings { get; private set; } 
} 

static class Program 
{ 
    static void Main() 
    { 
     // works fine now 
     var parent = new Parent 
     { 
      Child = 
      { 
       Strings = { "hello", "world" } 
      } 
     }; 

    } 
} 
+0

啊只讀屬性,謝謝! – Ajai

+4

集合初始化器與只讀屬性無關。此代碼的工作,因爲你把'字符串=新名單();'在構造函數,不是因爲酒店有'私人set'。 – GSerg

+0

再次閱讀代碼。 Child屬性不是集合,它是隻讀屬性。 –

17

它不是破碎的語法,它是你在一個屬性上使用對象初始值設定項,而這個對象初始值設定項沒有被實例化。你所寫的可擴展到

var parent = new Parent(); 
parent.Child.Strings = new List<string> { "hello", "world" }; 

會拋出的NullReferenceException:你想通過財產ChildChild仍然null包含的屬性Strings分配。 首先使用一個構造函數實例化Child,照顧這一點。

10

初始化沒有錯,但它試圖初始化不存在的對象。

如果類具有創建對象的構造函數,初始化工作:

class Parent { 
    public Child Child { get; set; } 
    public Parent() { 
    Child = new Child(); 
    } 
} 

class Child { 
    public List<string> Strings { get; set; } 
    public Child() { 
    Strings = new List<string>(); 
    } 
} 
0

引用不能老是總是在編譯時檢查空。雖然編譯器有時會在分配之前警告使用變量。編譯器正常工作。這是運行時錯誤。

4

你似乎誤解了集合初始化做什麼。

這是一個純粹的語法糖,在括號中的列表轉換成必須在集合對象初始化來定義series of calls to Add() method。因此
= { "hello", "world" }是有作爲

.Add("hello"); 
.Add("world"); 

顯然,這同樣的效果,如果沒有創建的集合將失敗,一個NullReferenceException。