C# Iterator迭代器模式我們在平時的開發中應該經常用到。不直接使用也會間接使用,我們使用foreach語句來循環就是在間接的使用C# Iterator迭代器模式。
迭代器就像指針一樣可以向前向後移動,在.NET中迭代器只能向後移動。
動機:在軟件的構建過程中,集合對象內部結構常常變化各異。但對於這些集合對象,我們希望在不暴露其內部結構的同時,可以讓外部客戶代碼透明地訪問其中包含的元素;同時這種“透明遍歷”也爲“同一種算法在多種集合對象上進行操作”提供了可能。使用面向對象技術將這種遍歷機制抽象爲“迭代器對象”爲“應對變化中的集合對象”提供了一種優雅的方式。
意圖:提供一種方法順序訪問一個集合對象中的各個元素,而不暴露該對象的內部表示。
- public interface IEnumerable{
- //得到迭代器
- IEnumerator GetEnumerator();
- }
- /// <summary>
- /// 迭代器接口
- /// summary>
- public interface IEnumerator{
- //得到當前的對象
- object Current{
- get;
- }
- bool MoveNext();
- void Reset();
- }
- /// <summary>
- /// 集合類型,實現了可迭代接口
- /// summary>
- public class MyCollection : IEnumerable{
- internal int[] items;
- public MyCollection(){
- items = new int[5] {1, 2, 3, 4, 5};
- }
- #region IEnumerable 成員
- //實現迭代接口,返回迭代器
- public IEnumerator GetEnumerator(){
- //在這裏進行解藕,將集合對象轉換爲迭代器
- return new MyEnumerator(this);
- }
- #endregion
- }
- //迭代器對象,實現了迭代器接口
- internal class MyEnumerator : IEnumerator{
- private int nIndex;
- MyCollection collection;
- //構造函數將集合類型轉換成內部成員
- public MyEnumerator(MyCollection coll){
- this.collection = coll;
- nIndex = -1;
- }
- #region IEnumerator 成員
- //返回當前迭代到的對象
- public object Current{
- get{
- return collection.items[nIndex];
- }
- }
- //移動到下一個對象,指針向後移動
- public bool MoveNext(){
- nIndex++;
- return (nIndex < collection.items.GetLength(0));
- }
- //重設迭代器,指針回零
- public void Reset(){
- nIndex = -1;
- }
- #endregion
- }
很清楚,在上面的代碼中,我們通過GetEnumerator方法,將集合對象轉換爲了可迭代對象,這實際上是在對集合對象進行抽象,將他轉換爲迭代器。在這裏,我們需要定義一個迭代器類,但是這是.NET 1.1中的做法,在.NET 2.0以後實現一個可迭代模式更加簡單。
- /// <summary>
- /// 集合類型,實現了可迭代接口
- /// summary>
- public class MyCollection : IEnumerable<int>
- {
- internal int[] items;
- public MyCollection()
- {
- items = new int[5] {1, 2, 3, 4, 5};
- }
- #region IEnumerable<int> 成員
- public IEnumerator<int> GetEnumerator()
- {
- for(int i = 0; i < items.Length; i++)
- {
- yield return items[i];
- }
- }
- #endregion
- #region IEnumerable 成員
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
- {
- for(int i = 0; i < items.Length; i++)
- {
- yield return items[i];
- }
- }
- #endregion
- }
我們通過yield return關鍵字來返回一個IEnumerator接口,這個關鍵在在編譯之後會自動生成對應的迭代器的代碼。
在.NET中迭代器只能先前,在c++中可以向後等其他操作。
注意:在迭代的過程中,我們不能向集合添加內容,後移除集合裏的item,這樣將會導致一些問題的出現。以上介紹C# Iterator迭代器模式。