首页 > 代码库 > 11.C#迭代器(六章6.1)

11.C#迭代器(六章6.1)

  今天我们说下C#中的迭代器,首先引出一些关于迭代的概念,后面举出代码供大家讨论。

  迭代器模式是行为模式的一种范例,行为模式是一种简化对象之间通信的一种设计模式。在.NET中使用IEnumerator和IEnumerable接口及它们的泛型等价物来封装的,如果一个类型实现了IEnumerable接口,就说明它是可迭代的,调用GetEnumerator方法返回IEnumerator的实现,这是迭代器本身。

  C#1使用foreach语句实现了访问迭代器的内置支持,foreach语句会被编译成使用GetEnumerator和MoveNext方法以及Current属性。C#中迭代器只能向后访问,而C++中迭代器可以支持前后访问。

  背景,假设有一个关于学生的队列,每个学生依次报出自己的名字,Student类如下

 1 class Student 2 { 3     public string Name { get; set; } 4  5     public Student(string name) 6     { 7         Name = name; 8     } 9 10     public void SayName()11     {12         Console.WriteLine(Name);13     }14 }

  有一个实现IEnumerable的Queue的泛型类,如下

 1 class Queue<T> : IEnumerable<T> where T : class 2 { 3     public List<T> objects = new List<T>(); 4  5     public Queue(List<T> list) 6     { 7         objects = list; 8     } 9 10     //实现从IEnumerable中的GetEnumerator方法11     /*12         个人觉得这个方法在迭代中只会调用一次,不然每次都返回一个新的QueueIterator<T>对象,位置记录都会重置为-113     */14     public IEnumerator<T> GetEnumerator()15     {16         return new QueueIterator<T>(this);  17     }18 19     IEnumerator IEnumerable.GetEnumerator()20     {21         throw new NotImplementedException();22     }23 }

  使用GetEnumerator方法返回一个迭代器,而迭代器需要实现IEnumerator接口,如下

 

 1 class QueueIterator<T> : IEnumerator<T> where T : class 2 { 3     private ConsoleDemo.Chapter6.Queue<T> q = null; 4  5     int startPoint = -1;    //用于保存游标的位置 6  7     public QueueIterator(ConsoleDemo.Chapter6.Queue<T> q) 8     { 9         this.q = q;10     }11 12     //返回合适位置上的T类型实例,这个例子中调用提这个自动属性13     public T Current14     {15         get16         {17             if (startPoint==-1 || startPoint==q.objects.Count)18             {19                 throw new InvalidOperationException();20             }21             int index = startPoint + q.objects.Count;22             index = index % q.objects.Count;23             return q.objects[index];24         }25     }26 27     object IEnumerator.Current28     {29         get30         {31             if (startPoint == -1 || startPoint == q.objects.Count)32             {33                 throw new InvalidOperationException();34             }35             int index = startPoint + q.objects.Count;36             index = index % q.objects.Count;37             return q.objects[index];38         }39     }40 41     public void Dispose()42     {43         44     }45 46     public bool MoveNext()47     {48         if (startPoint != q.objects.Count)49         {50             startPoint++;51         }52         return startPoint < q.objects.Count;53     }54     //当迭代结束后,会调用这个方法,则下一次迭代后重新从第一个位置开始55     public void Reset()56     {57         startPoint = -1;58     }59 }

  分别要去实现从IEnumerator中的Current属性、Dispose方法(有必要的话)、MoveNext方法、Reset方法。使用C#2中的yield语句可以简化迭代器,再下一篇中再说。

  请斧正。

 

 

 

  

11.C#迭代器(六章6.1)