DAY 21 迭代器
迭代器
迭代器我找不到一個好的解釋,所以請看完本文後自行領悟吧。
迭代器的關鍵字 yield,只有在傳回值為 IEnumerator
然而各位還記得 DAY 05 的 foreach 吧,foreach 的逐一查看陣列、集合中的元素就是透過今天要介紹的迭代器。
foreach 有些集合類別能用,有些不能使用,差別在於有無實作 IEnumerator
我們來簡單的示範什麼是迭代器,所先建立一個傳回 IEnumerable
1 | static void Main (string[] args) { |
可以下中斷點來看一下程式的執行過程,這樣比較好了解迭代器做了什麼,你可以看到程式執行過程,不斷的跳來跳去。
迭代器主要是實現 IEnumerator 介面來執行,成員為 Current 與 MoveNext (),你可以想像成一個集合內,Current 代表目前元素,MoveNext () 為檢查有無下個元素。當程式呼叫迭代器時,他會先檢查 MoveNext (),如果有則移動 Current,直到沒有下一個元素。
但上述方法只是簡單的示範 yield 運作模式,無實作 IEnumerator 介面,你可以先當作 yield return 為傳回一個 Current,如果有下一句 yield return 則 MoveNext () 為 true,然而碰到 yield break 則結束迭代。
除此之外也可以看到,strs 在傳值給 str 時,才會開始迭代,因為迭代器有延遲執行的特性,所以在資料處理方面,與一般的情況不太一樣。以往處理資料時,是整理好一大筆符合資料後才傳回,但迭代器則是出現一筆符合資料的就傳回,直到該集合逐一檢查完成。
再來我們以 DAY 18 的 Node 來進行改造,讓他可以使用 foreach,但在此之前要先說一聲抱歉,我那天寫的時候可能神智不清楚,所以在操作 Node 時的範例不是很洽當,但還是可以當作泛型的介紹,所以我們重新來建立新的 Node
1 | class Program { |
有發現差異點吧,沒有的同學就當沒事發生。
當今天要去逐一查看 Node 的內容時,我們想要重頭開始列出每一個 Node 的 value 直到 Next == null,所以我們來實作 IEnumerable
1 | class Program { |
簡單的設計一下,就可以看到 foreach 能夠正確的印出 Node 裡每一個 value 值。
既然做了那我們來優化一下,提供一個可以知道該 Node 包含的 Node 數的 Length,並加上索引存取運算子。
1 | public int Length { |
可以自行使用看看,這邊就不用在教導如何使用了吧。
一些小結論
迭代器可以實現延遲執行,可以參考文末連結,或者自己再去找找資源補充一下,我敘述的可能有點混亂,好處也就是資料的傳回方式不一樣,可能還有其他的,但我不知道而已,可能這樣寫看起來很潮也是好處之一。
在最後補上的兩個方法,想說介紹一下存取子的用法,已經寫到不知道有沒有寫過了,大致上再講一遍,如果講過就當複習吧。
存取子可以控制屬性成員的讀寫運算機制。
get 為讀取,如果只有 get 如上述範例,則可以表示該屬性唯獨,並可以控制它讀取時傳回的內容。
set 為寫入,如果只有 set 則表示該屬性唯寫,如寫入一個數字時永遠加二這個邏輯,但個人是沒有碰過唯寫屬性的例子,如果使用一般會跟著 get 一起。
get & set 為可讀可寫,可以控制讀取的傳回值,與設定時的邏輯。正常什麼都不做的情況預設就是 get & set,但讀寫時無任何規則,單純的操作屬性而已。
感謝閱讀。