[.NET]快快樂樂學LINQ系列前哨戰-IEnumerable, IEnumerable<T>與Enumerable
前言
繼上一篇提到了IEnumerable
, IEnumerable<T>
, IEnumerator
, IEnumerator<T>
與foreach的關係,這一篇要講Enumerable
與IEnumerable
, IEnumerable<T>
的關係。(很痛苦嗎?前哨戰快結束了,這些都是LINQ運作的基礎)
關係圖
一樣,先用一張圖來說明關係。
簡單的說,IEnumerable
與IEnumerable<T>
,只是介面與泛型介面的差異。而它們都是用來供foreach展開的介面。
我們這篇的重點放在Enumerable
,這個class上面。
說明
簡單的說,Enumerable
是一個static class,上面基本上只放了三類東西:
-
針對
IEnumerable
的Extension Method。 -
針對
IEnumerable<T>
的Extension Method。 -
Enumerable
class本身的靜態方法。
不了解Extension Method的讀者們,可以參考之前的文章:[.NET]快快樂樂學LINQ系列前哨戰-擴充方法(Extension Method)
來看一下這個class的基本結構:
可以看到,System.Core.dll中,針對Enumerable
類別的描述是:
// 摘要:
// 提供一組 static (在 Visual Basic 中為 Shared) 方法,用於查詢實作 System.Collections.Generic.IEnumerable<T>
// 的物件。
也就是,Enumerable
這個static class,最主要的目的,就是針對IEnumerable<T>
進行擴充,讓所有有實作IEnumerable<T>
的型別,都可以享用這些方法。
而針對IEnumerable
介面,Enumerable
類別則提供了兩個常見的方法:Cast<T>
, OfType<T>
,而這兩個方法,簡單的說,就是把IEnumerable
轉成IEnumerable<T>
泛型介面。當然中間還有一點點的差異,Cast<T>
是把IEnumerable
中的Element都轉型成T,而OfType<T>
則是把IEnumerable
中,屬於T型別的Element都抽出來。透過這兩個方法處理後,其型別都變成了IEnumerable<T>
,就可以享用IEnuemrable<T>
上,所有的擴充方法。
然而Enumerable
類別,也擁有了非Extension Method的靜態方法,如Range
與Repeat<T>
。Range
簡單來說,就是產生一組IEnumerable<int>
,傳start與count兩個參數,就可以建立一組數字序列。(也就是幫你把for迴圈+yield封裝成方法了)而Repeat<T>
則是幫你產生一個重複n個T的序列,結果型別就是IEnumerable<T>
。簡單的說,就是從沒有序列,呼叫這兩個方法,就可以產生常見需求的IEnumerable<T>
,接著就可以享用IEnumerable<T>
上,所有的擴充方法。
by the way, 各位別忘了上一篇說明擴充方法時提到的,需要引用該namespace,擴充方法才會作用。
結論
可以說System.Linq這個namespace的精髓,就在Enumerable
這個類別上,而這個類別幾乎不曾看過。因為它最大的職責,是針對IEnumerable<T>
介面進行擴充。而可以用foreach展開的型別,就一定有實作IEnumerable
或IEnumerable<T>
這兩個介面。
換言之,可以用foreach展開的型別,就可以用LINQ來處理。
再延伸出去一些,IEnumerable<T>
的擴充方法,也就是LINQ所提供的方法,就是透過泛型委派等參數(就是那一堆Func<T1, T2, …Tn, TResult>
的東西),來簡化常見、複雜、囉嗦、麻煩的foreach迴圈的處理。
blog 與課程更新內容,請前往新站位置:http://tdd.best/