迭代器

  1 /*
  2  IEnumerator 接口
  3 支持对非泛型集合的简单迭代。 
  4 
  5 IEnumerator 是所有非泛型枚举数的基接口。
  6 
  7 
  8 C# 语言的 foreach 语句(在 Visual Basic 中为 for each)隐藏了枚举数的复杂性。
  9 
 10 枚举数可用于读取集合中的数据,但不能用于修改基础集合。
 11 
 12 最初,枚举数定位在集合中第一个元素前。Reset 方法还会将枚举数返回到此位置。在此位置,调用 Current 属性会引发异常。因此,在读取 Current 的值之前,必须调用 MoveNext 方法将枚举数提前到集合的第一个元素。
 13 
 14 在调用 MoveNext 或 Reset 之前,Current 返回同一对象。MoveNext 将 Current 设置为下一个元素。
 15 
 16 如果 MoveNext 越过集合的末尾,则枚举数将被放置在此集合中最后一个元素的后面,而且 MoveNext 返回 false。当枚举数位于此位置时,对 MoveNext 的后续调用也返回 false。如果最后一次调用 MoveNext 返回 false,则调用 Current 会引发异常。若要再次将 Current 设置为集合的第一个元素,可以调用 Reset,然后再调用 MoveNext。
 17 
 18 只要集合保持不变,枚举数就保持有效。如果对集合进行了更改(如添加、修改或删除元素),则枚举数将失效且不可恢复,并且下一次对 MoveNext 或 Reset 的调用将引发 InvalidOperationException。如果在 MoveNext 和 Current 之间修改集合,那么即使枚举数已经无效,Current 也将返回它所设置成的元素。
 19 
 20 枚举数没有对集合的独占访问权;因此,枚举通过集合在本质上不是一个线程安全的过程。即使一个集合已进行同步,其他线程仍可以修改该集合,这将导致枚举数引发异常。若要在枚举过程中保证线程安全,可以在整个枚举过程中锁定集合,或者捕捉由于其他线程进行的更改而引发的异常。
 21 
 22  */
 23 
 24 
 25 using System;
 26 using System.Collections.Generic;
 27 using System.Collections;
 28 using System.Linq;
 29 using System.Text;
 30 
 31 namespace ConsoleApplication1
 32 {
 33     public class Person
 34     {
 35         public string firstName;
 36         public string lastName;
 37 
 38         public Person(string fName, string lName)
 39         {
 40             this.firstName = fName;
 41             this.lastName = lName;
 42         }
 43     }
 44 
 45     public class People : IEnumerable
 46     {
 47         private Person[] _people;
 48         public People(Person[] pArray)
 49         {
 50             _people = new Person[pArray.Length];
 51 
 52             for (int i = 0; i < pArray.Length; i++)
 53             {
 54                 _people[i] = pArray[i];
 55             }
 56         }
 57 
 58         public IEnumerator GetEnumerator()
 59         {
 60             return new PeopleEnum(_people);
 61 
 62         }
 63     }
 64 
 65 
 66     public class PeopleEnum : IEnumerator
 67     {
 68         public Person[] _people;
 69 
 70         // Enumerators are positioned before the first element
 71         // until the first MoveNext() call.
 72 
 73         int position = -1;
 74 
 75         public PeopleEnum(Person[] list)
 76         {
 77             _people = list;
 78         }
 79 
 80         public bool MoveNext()
 81         {
 82             position++;
 83             return (position < _people.Length);
 84         }
 85 
 86         public void Reset()
 87         {
 88             position = -1;
 89         }
 90 
 91         public object Current
 92         {
 93             get
 94             {
 95                 try
 96                 {
 97                     return _people[position];
 98                 }
 99                 catch (IndexOutOfRangeException)
100                 {
101                     throw new InvalidOperationException();
102                 }
103             }
104         }
105     }
106 
107 
108     public class DogEnum : IEnumerator
109     {
110 
111         #region IEnumerator 成员
112 
113         public object Current
114         {
115             get { throw new NotImplementedException(); }
116         }
117 
118         public bool MoveNext()
119         {
120             throw new NotImplementedException();
121         }
122 
123         public void Reset()
124         {
125             throw new NotImplementedException();
126         }
127 
128         #endregion
129     }
130 
131     class Program
132     {
133         static void Main(string[] args)
134         {
135             Person[] peopleArray = new Person[3]
136             {
137                 new Person("John", "Smith"),
138                 new Person("Jim", "Johnson"),
139                 new Person("Sue", "Rabon")
140             };
141 
142             People peopleList = new People(peopleArray);
143 
144             //foreach
145             foreach (Person p in peopleList)
146             {
147                 Console.WriteLine(p.firstName + " " + p.lastName);
148             }
149 
150             //foreach本质上是这样调用的
151             IEnumerator myrator = peopleList.GetEnumerator();
152             myrator.Reset();
153             while (myrator.MoveNext())
154             {
155                 Person p = (Person)myrator.Current;
156                 Console.WriteLine(p.firstName + " " + p.lastName);
157             }
158         }
159     }
160 }

 

posted @ 2018-11-10 09:52  冬夜的火  阅读(133)  评论(0编辑  收藏  举报