本篇將圍繞 《試試 IEnumerable 的 10 個小例子》和《試試 IEnumerable 的另外 6 個小例子》給出的例子,總結一下對於 IEnumerable
接口的一些使用方法,但願讀者可以從中得到一些啓發。html
對於一個實現了 IEnumerable
接口的類型來講,開發中最經常使用的,就是把這個類型的對象放入到 foreach
等循環關鍵詞中進行迭代,遍歷其中的元素進行處理。git
這種遍歷一般分爲兩種目的:遍歷和查找。github
IEnumerable
及其泛型版本 IEnumerable<T>
定義了一個類型的 「可迭代性」。這點很容易理解,系統中的不少集合類型都實現了該接口。算法
所以這些集合類型都可以採用 foreach
進行迭代遍歷。可是每一個集合類型的迭代方式和結果是不徹底相同的,這取決於集合自己的特性。例如:編程
List<>
、Stack<>
和 Queue<>
的迭代的順序不相同,由於數據結構自己要求是不一樣的ConcurrentDictionary<,>
和 Dictionary<,>
在迭代時的線程安全性是不一樣的,由於針對線程安全的設計是不一樣的BlockingCollection.GetConsumingEnumerable
方法返回一個會產生阻塞的消費者對象,因此,即便都是丟進 foreach
,可是效果也是不徹底同樣的。使用這些,須要讀者對這些類型自己須要增進了解。安全
建議讀者在使用框架中實現了 IEnumerable
的類型時,必定要注意迭代的細節,能夠經過 MSDN 上的文檔瞭解其特殊性。網絡
Linq 是一個說小不小的話題,這裏只是說其中的 Linq To Object 部份內容。數據結構
經過 Linq 中提供的一些擴展方法,能夠方便的控制對於一個 IEnumerable
對象的迭代方式。經過這些方法的應用,能夠在不少時候避免複雜的條件和循環嵌套。框架
同時,Linq 中抽象的 Func 和 Action,也要求開發人員在平時的編寫過程當中注意對於迭代自己的歸類和整理。Where(IsLeapYear)
會比 Where(x=>(x % 4 == 0 && x % 100 != 0) || x % 400 == 0)
來的更加容易閱讀。異步
除了基礎的數據結構,開發過程當中有時須要自定義一些集合類型。這些集合類型須要本身實現一個迭代過程。例如:二叉樹及其遍歷,對列表進行分頁等等。
這些數據結構的迭代一般須要特定算法的支持。
在《試試 IEnumerable 的另外 6 個小例子》中關於樹的幾個例子便數據此類中。
在 C#7.0 引入了本地函數以後, IEnumerable
結合本地函數,快速實現自定義迭代過程的奇怪操做也就跟着出現。
經過這種操做能夠在一個函數內採用一些之前不容易實現的方式實現一些操做:
這相關的例子在《試試 IEnumerable 的 10 個小例子》中較多。
按照月老闆的名言:「業務複雜度是不會由於系統設計變化而減小的,它只是從一個地方轉移到了另外的地方。」,咱們能夠知道,這種寫法其實沒有使得原來就有的判斷和循環變少。只是改變了語法結構。
讀者能夠將這種操做做爲一種 「語法糖」 進行使用。若是是在團隊項目中,則須要尊重團隊成員的共贊成見,由於這種操做並不是全部人都願意接受。
固然,這種作法在一些地方會產生好處。例如在將本地函數、IEnumerable 和 Task 相結合的 T10 測試網絡鏈接 中。這種寫法就減小了傳統寫法中須要建立一個 List
或者 Array
的開銷。
總之,這種寫法,提供了一種新的思路。是否必定要使用,將取決於讀者團隊的接受程度。
在 C# 8 和 .netcore 3.0 到來的版本中,咱們迎接到了 IAsyncEnumerable
接口來實現異步迭代器的功能。
IEnumerable
是同步方法的迭代器,IAsyncEnumerable
能夠看作是其異步版本。有了這個接口,那麼在迭代的過程當中也能夠充分利用 async/await 帶來的編程快感。
本系列中沒有添加這部分的示例,可是主體思路是一致的。
她的出現,只會使得開發者更容易應用以上總結的幾種主要場景。
詳細的例子,能夠參見相關文章進行了解。
本系列到此便結束了,但願讀者多在實踐中體會以上總結的幾種使用場景。
本系列中的例子已經所有使用 dotnetfiddle.net 進行了重寫,讀者能夠直接在本博客的頁面上運行這些示例。
若是沒法正常的展現示例,讀者也能夠經過本倉庫下載示例相關的代碼。