C#中LINQ與數據管道

假如有一個集合,裏面有數字1-10,現在想實現從這10個數字中取出偶數數字,然後將得到的偶數乘以10,最後輸出前三個。代碼如下:

代碼非常的簡單,最後會得到20、40、60這三個數字,但結果並不是我們今天最關注的事。今天我們想討論下numbers中的數字是如何Where、Select、Take這三個方法中流轉的。也許你會認爲,是這樣流轉的。如下:

一般我們會向上圖這樣理解:Where中生成並返回符合條件的新數組,然後將這個數組交個Select處理,Select中生成並返回新數組,再交由Take處理,Take取出前三個數並返回新數組。

其實並不是這樣,我們知道Linq是由一系列基於IEnumerable的擴展方法組成,返回值也都是IEnumerable,而IEnumerable只是一個迭代器對象,每次讀取IEnumerable對象時,其實只是遍歷裏面的一個元素。上面方法的真正流程應該是流式的類似管道的操作,即讀一個數字處理一個,邊讀邊處理。如下:

這樣數據逐個在方法中處理就構成了數據管道,這裏還有一個地方需要注意,很多Linq方法是延遲操作,比如我們例子中的Where、Select、Take這些,但ToList、Count、Sum會立即執行。延遲操作就是隻是定義如何操作數據,但不會真正執行,等到數據真正使用的時候纔會執行。我們來驗證下,比如我在Select中故意拋一個異常,試下。代碼如下:

我們再次執行一下,異常不會報出。代碼如下:

其實代碼中的filter變量可以理解成一堆算法的包裝器,只是封裝了一系列對數據的操作,但只有元素被使用時纔會執行。我們在代碼後加一段遍歷filter並輸出的代碼,這時元素被使用到了,就會報錯了。代碼如下:

好了,我們要講的內容就講完了,內容非常淺,相信很多人都是知道的,大家可以去看下Linq的源碼,相信收穫會更多。管道的思想其實應用非常多,比如鏈式編程、建造者模式,在dotcore中用的就更多了。

高冷地說聲拜拜~~


本文分享自微信公衆號 - 一線碼農聊技術(dotnetfly)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章