迭代器模式(Iterator),提供一種方法順序訪問一個聚合對象中的各種元素,而又不暴露該對象的內部表示。C#中使用IEnumerator接口實現,Java中使用Iterator接口實現,其中原理都差不多,下面我就用C#代碼來演示下迭代器的實現。
假如我要實現一個自定義容器列表,就叫它SpecialList吧,可以實現類似ArrayList的功能。如下:

這個時候我想遍歷這個列表,當我使用foreach的時候,報錯了。如下:

提示SpecialList不包含GetEnumerator的公共實例定義,在C#中,如果想要使用foreach遍歷列表對象,這個列表對象必須要實現IEnumerable的GetEnumerator()方法,我們來加一下。如下:

繼承后,foreach列表的時候就不會再報錯了,但我們並沒有實現GetEnumerator()這個方法。我們看一下這個方法的返回值類型為IEumerator,F12進去看一下這個接口的定義。如下:

這個接口里面有兩個方法和一個屬性。其中MoveNext()是最核心的方法,就是在這個里面實現列表的遍歷。話不多說,我們先定義一個繼承IEnumerator的類,就叫SpecialEnumerator吧。如下:

不好意思,我已經簡單的寫好這個類了,那就簡單的講一個這個類的原理吧。SpecialEnumerator主要定義了一個SpecialList類型的_list,還有當前元素的_current,還有當前索引的_index。我們重點看一下MoveNext方法,里面的代碼其實也非常簡單,就是判斷_index是否已經到底,沒有的話叫取出當前_index上的元素賦予_cuurent,然后返回true,這里的返回值給到foreach,如果為true,則繼續遍歷,如果為false,則foreach跳出循環。我們再來看一下SpecialList中怎么使用SpecialEnumerator類。如下:

這樣只是返回SpecialEnumerator的一個實例,同時將當前要枚舉的列表對象(this)傳入進去。
你可能會有疑問,這里只是返回一個對象,在foreach中並沒有循環判斷MoveNext是true還是false的代碼,那它是怎么實現的呢?其實foreach只是一個語法糖,它本質上其實是使用了while語法來實現的。如下:

到這里,相信大家已經明白迭代器是怎么實現的了。最后再補充一下,大家可能會覺得額外實現SpecialEnumerator類比較繁瑣,其實如果你的列表遍歷規則比較簡單的話,可以使用yield語法來代替SpecialEnumerator類,只要這樣寫就行。如下:

但如果你的列表遍歷規則比較特殊,比如像棧、隊列這樣的容器類時,還是建議實現枚舉類,這樣可以將遍歷規則封裝在MoveNext中。
感謝閱讀,如果覺得不錯,給個【推薦】吧!
更多精彩內容,可關注我的公眾號:
