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 }