這讓我覺得奇怪的是,從IEnumerable<T>
繼承任何類並不需要實現Add(T object)
,即使如果你想初始化類實例時使用collection initializers,你必須實現Add(T object)
。添加(T對象)不是IEnumerable的合同方法<T> - 爲什麼?
爲什麼這樣呢?
這讓我覺得奇怪的是,從IEnumerable<T>
繼承任何類並不需要實現Add(T object)
,即使如果你想初始化類實例時使用collection initializers,你必須實現Add(T object)
。添加(T對象)不是IEnumerable的合同方法<T> - 爲什麼?
爲什麼這樣呢?
IEnumerable<T>
是一個只讀接口 - 它只是爲了表示「一個序列」。
集合初始化需要爲了工作Add
,但他們檢查類型實現IEnumerable
首先要確保它確實是一些描述集合類型。它們不要求通用形式,因爲對於某些2.0之前的代碼會有限制(特別是各種UI集合不實現IEnumerable<T>
IIRC),並且它們不需要特定的Add
簽名,因爲可以使用集合初始化器具有不同數量的參數。例如,Dictionary<TKey, TValue>
有Add(TKey value, TValue value)
所以你可以使用:
var dictionary = new Dictionary<string, int>
{
{ "Jon", 33 },
{ "Tom", 6 }
};
這意味着它不能僅限於(比如說)IList
其中只有單argumnet Add
方法。它在某種程度上需要鴨子打字,但IEnumerable
要求是試圖確保Add
確實意味着「向集合添加項目」而不是完全不同的東西。編譯器不會使用它實現IEnumerable
的事實 - 例如,在構建集合時從不調用GetEnumerator
。
IEnumerable是「堆棧」的底層,它具有枚舉整個列表所需的基礎知識,這使它成爲只讀函數。
我想最大的原因是並非所有的集合都必須是Enumerable。此外,事實上你可以有其他可枚舉的項目,比如計算或其他過程。
例如,您可以使用帶有Yield命令的IEnumerable來計算出素數或Fibonacci序列。這真的取決於你。
至於集合初始值設定項,因爲您正在處理集合,我假設初始值設定項可能使用類似於Yield命令的項目,所以它使用IEnumerable將您初始化的值生成爲Add方法。
我的兩分錢。
更令人信服的原因是並非所有的枚舉都需要是集合。 – erikkallen 2009-12-18 11:51:38
正如其他人所說,IEnumerable
是一個只讀接口,指示一個序列可以迭代,僅此而已。
什麼是集合:
你寬約爲什麼收集initialisers需要
IEnumerable
組合和Add
方法可能best addressed by Mads Torgersen問題?然後我們發現了什麼?我們的 自己的(公共)班級(與公衆 構造函數)中只有14個實施
ICollection<T>
!很明顯,在框架中有 很多收藏, 所以很明顯,我們需要一些 其他方式來告訴 是否是一個集合類。 LINQ到 救援一次:隨着修改 版本的查詢很容易 建立我們的公共 類與公共構造有 之間的有:
189具有公共
Add
方法實施System.Collections.IEnumerable
42具有公共
Add
方法,但沒有實現System.Collections.IEnumerable
如果你看一下由 這兩個查詢返回的類,你就會意識到, 主要有兩種 的 根本不同含義的名字「添加」:
a)將參數變成 集合,或
b)返回參數和接收方的算術和 。
的人實際上是在 (直接或間接)寫的集合類時實施 非泛型
IEnumerable
接口 非常好,所以 這原來是一個Add
方法是否是 一個相當可靠的 指標第一或第二種。因此,對於 我們的目的操作答案 標題問題就變成了:集合是實現
IEnumerable
並具有公共Add
方法
直接從馬的嘴這裏輸入:http ://blogs.msdn.com/madst/archive/2006/10/10/What-is-a-collection_3F00_.aspx – LukeH 2009-12-18 11:48:55
值得注意的是'foreach'確實在'IEnumerable'上使用鴨子打字,所以有可能迭代使用'foreach'而不能使用集合初始值設定項。 – thecoop 2009-12-18 11:50:11