今天我們說下C#中的迭代器,首先引出一些關(guān)于迭代的概念,后面舉出代碼供大家討論。
迭代器模式是行為模式的一種范例,行為模式是一種簡(jiǎn)化對(duì)象之間通信的一種設(shè)計(jì)模式。在.NET中使用IEnumerator和IEnumerable接口及它們的泛型等價(jià)物來封裝的,如果一個(gè)類型實(shí)現(xiàn)了IEnumerable接口,就說明它是可迭代的,調(diào)用GetEnumerator方法返回IEnumerator的實(shí)現(xiàn),這是迭代器本身。
C#1使用foreach語句實(shí)現(xiàn)了訪問迭代器的內(nèi)置支持,foreach語句會(huì)被編譯成使用GetEnumerator和MoveNext方法以及Current屬性。C#中迭代器只能向后訪問,而C++中迭代器可以支持前后訪問。
背景,假設(shè)有一個(gè)關(guān)于學(xué)生的隊(duì)列,每個(gè)學(xué)生依次報(bào)出自己的名字,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 }有一個(gè)實(shí)現(xiàn)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 //實(shí)現(xiàn)從IEnumerable中的GetEnumerator方法11 /*12 個(gè)人覺得這個(gè)方法在迭代中只會(huì)調(diào)用一次,不然每次都返回一個(gè)新的QueueIterator<T>對(duì)象,位置記錄都會(huì)重置為-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方法返回一個(gè)迭代器,而迭代器需要實(shí)現(xiàn)IEnumerator接口,如下
1 class QueueIterator<T> : IEnumerator<T> where T : class 2 { 3 PRivate ConsoleDemo.Chapter6.Queue<T> q = null; 4 5 int startPoint = -1; //用于保存游標(biāo)的位置 6 7 public QueueIterator(ConsoleDemo.Chapter6.Queue<T> q) 8 { 9 this.q = q;10 }11 12 //返回合適位置上的T類型實(shí)例,這個(gè)例子中調(diào)用提這個(gè)自動(dòng)屬性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 //當(dāng)?shù)Y(jié)束后,會(huì)調(diào)用這個(gè)方法,則下一次迭代后重新從第一個(gè)位置開始55 public void Reset()56 {57 startPoint = -1;58 }59 }分別要去實(shí)現(xiàn)從IEnumerator中的Current屬性、Dispose方法(有必要的話)、MoveNext方法、Reset方法。使用C#2中的yield語句可以簡(jiǎn)化迭代器,再下一篇中再說。
請(qǐng)斧正。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注