[.NET]快快樂樂學LINQ系列前哨戰-IEnumerable, IEnumerable<T>與Enumerable

[.NET]快快樂樂學LINQ系列前哨戰-IEnumerable, IEnumerable<T>與Enumerable

前言

繼上一篇提到了IEnumerable, IEnumerable<T>, IEnumerator, IEnumerator<T>與foreach的關係,這一篇要講EnumerableIEnumerable, IEnumerable<T>的關係。(很痛苦嗎?前哨戰快結束了,這些都是LINQ運作的基礎)

 

關係圖

一樣,先用一張圖來說明關係。

關係圖

簡單的說,IEnumerableIEnumerable<T>,只是介面與泛型介面的差異。而它們都是用來供foreach展開的介面。

我們這篇的重點放在Enumerable,這個class上面。

 

說明

簡單的說,Enumerable是一個static class,上面基本上只放了三類東西:

  1. 針對IEnumerable的Extension Method。
  2. 針對IEnumerable<T>的Extension Method。
  3. Enumerable class本身的靜態方法。

不了解Extension Method的讀者們,可以參考之前的文章:[.NET]快快樂樂學LINQ系列前哨戰-擴充方法(Extension Method)

來看一下這個class的基本結構:

image

可以看到,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的靜態方法,如RangeRepeat<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展開的型別,就一定有實作IEnumerableIEnumerable<T>這兩個介面。

換言之,可以用foreach展開的型別,就可以用LINQ來處理。

再延伸出去一些,IEnumerable<T>的擴充方法,也就是LINQ所提供的方法,就是透過泛型委派等參數(就是那一堆Func<T1, T2, …Tn, TResult>的東西),來簡化常見、複雜、囉嗦、麻煩的foreach迴圈的處理。


blog 與課程更新內容,請前往新站位置:http://tdd.best/