第 91 講:C# 3 之集合初始化器
下面我們來看第二種初始化器語法:集合初始化器。
對于數(shù)組來說,數(shù)組的初始化器對數(shù)組對象的初始化來說相當(dāng)方便。但是很遺憾的是,也就數(shù)組有初始化器。對于 List<>
類型來說,它們也需要初始化,但 List<>
這些集合類型并沒有合適的初始化器語法,因此非常不方便,你只能使用 Add
方法挨個添加元素。
好在,C# 的集合類型,添加元素全都叫 Add
,這促使了 C# 語言的語法設(shè)計團隊定義出了一種新的語法。
Part 1 數(shù)組初始化器的推廣
C# 3 開始,允許各種各樣的集合使用類似數(shù)組初始化器的語法來添加、追加元素到集合里。就拿常見的 List<>
類型來說,原本的語法是這樣的:
C# 3 允許這么寫了:
我們把類似數(shù)組初始化器的語法放在集合的初始化操作之中的 { 1, 3, 6, 10 }
這個東西叫做集合初始化器(Collection Initializer)。
Part 2 集合初始化器的使用條件
我們從前面的規(guī)則來看,集合初始化器都既然叫集合初始化器了,顯然這個語法適用于一個集合??蓡栴}在于,從嚴(yán)謹(jǐn)?shù)慕嵌葋碚f,啥樣的東西才能叫集合呢?這種比較意識流的概念肯定是不能放在 C# 的語法設(shè)計里去的。
這里就得重新提及鴨子類型的概念了。在之前我們介紹過鴨子類型的基本概念,以及第一種鴨子類型的語法:foreach
循環(huán)的滿足條件。要想一個數(shù)據(jù)類型的實例可以使用 foreach
循環(huán),必須要求對象要么實現(xiàn) IEnumerable
或者 IEnumerable<>
接口,要么自己實現(xiàn)相關(guān)的迭代器模式,即定義一個類型,實現(xiàn) bool
返回值的 MoveNext
方法和返回實例的 Current
屬性。
今天我們要學(xué)習(xí)的集合初始化器是第二種鴨子類型語法。它需要滿足一個條件,才能允許使用。
先說結(jié)論:集合初始化器需要這個數(shù)據(jù)類型實現(xiàn) IEnumerable
接口或者從它派生下來接口,并包含一個不返回任何數(shù)值的 Add
方法,傳入一個參數(shù)表示存到集合里去。
意思應(yīng)該比較清晰了吧。我們回到 List<>
類型,發(fā)現(xiàn) List<>
在 C# 3 上天生就支持這個集合初始化器的語法,就是因為它滿足我們剛才說的這兩個條件。首先,List<>
集合里包含 Add
方法,void
返回值,并傳入 T
類型的參數(shù),所以滿足了第二個條件;并且這個集合也實現(xiàn)了 IEnumerable<T>
接口。這個接口是從非泛型版本的 IEnumerable
接口派生的,因此它算是滿足了第一個條件。正是因為這個對象滿足了兩個條件,因此它可以認(rèn)定為“可以使用集合初始化器的語法”。
注意這個鴨子類型的語法。這次的語法必須要求實現(xiàn)接口,但 foreach
滿足條件里不一定需要實現(xiàn)接口,而是只需要有迭代器模式的代碼就行,所以一定要區(qū)分開。
Part 3 其它細節(jié)
3-1 允許在末尾多一個額外的逗號
這個語法和對象初始化器差不太多,也可以省略無參構(gòu)造器的小括號,也允許集合初始化器最后一個元素后面的額外的逗號。
3-2 不要混用集合初始化器和對象初始化器
雖然這樣的語法很好用,但很遺憾的是,C# 并不允許混用對象初始化器和集合初始化器。下面的語法就不可以:
Add