迭代器也是C# 2.0的產物。
1.1 迭代器的簡介
迭代器記錄了集合中的某個位置,它使程序只能向前移動。C# 1.0中使用foreach語句來實現訪問迭代器的內置支持,foreach使遍歷集合變得簡單,它比for語句更方便,也更容易理解。foreach被編譯器編譯後,會調用GetEnumerator來返回一個迭代器,也就是一個集合中的初始位置。
1.2 C# 1.0中如何實現迭代器
一個類型想要使用foreach關鍵字進行遍歷,它必須實現IEnumerable或IEnumerable<T>接口。IEnumerable接口中定義了一個GetEnumerator方法用來返回迭代器,類型如果實現了IEnumerable接口,則也必須實現GetEnumerator方法。
1 namespace 迭代器
2 {
3 class Program
4 {
5 static void Main(string[] args)
6 {
7 Friends friendcollection=new Friends();
8 foreach (Friend friend in friendcollection)
9 {
10 Console.WriteLine(friend.Name);
11 }
12 Console.ReadKey();
13 }
14 }
15
16 public class Friend
17 {
18 private string name;
19 public string Name
20 {
21 get { return name; }
22 set { name = value; }
23 }
24
25 public Friend(string name)
26 {
27 this.name = name;
28 }
29 }
30
31 public class Friends : IEnumerable
32 {
33 private Friend[] friendarray;
34
35 public Friends()
36 {
37 friendarray=new Friend[]
38 {
39 new Friend("張三"),
40 new Friend("李四"),
41 new Friend("王五"),
42 };
43 }
44
45 //索引器
46 public Friend this[int index] => friendarray[index];
47
48 public int Count => friendarray.Length;
49
50 //實現IEnumerable<T>接口的方法
51 public IEnumerator GetEnumerator()
52 {
53 return new FriendIterator(this);
54 }
55 }
56
57 public class FriendIterator : IEnumerator
58 {
59 private readonly Friends friends;
60 private int index;
61 private Friend current;
62 internal FriendIterator(Friends friendcollection)
63 {
64 this.friends = friendcollection;
65 index = 0;
66 }
67
68 public bool MoveNext()
69 {
70 if (index + 1 > friends.Count)
71 {
72 return false;
73 }
74 else
75 {
76 this.current = friends[index];
77 index++;
78 return true;
79 }
80 }
81
82 public void Reset()
83 {
84 index = 0;
85 }
86 //實現IEnumerator接口中的方法
87 public object Current => this.current;
88
89 }
90 }
從以上的代碼可以看出,在C# 1.0中,要使用某個類型可以迭代是需要寫大量代碼的。
1.3 C# 2.0簡化了迭代器的實現
不說這麼多,直接上代碼:
1 namespace 迭代器
2 {
3 class Program
4 {
5 static void Main(string[] args)
6 {
7 Friends friendcollection=new Friends();
8 foreach (Friend friend in friendcollection)
9 {
10 Console.WriteLine(friend.Name);
11 }
12 Console.ReadKey();
13 }
14 }
15
16 public class Friend
17 {
18 private string name;
19 public string Name
20 {
21 get { return name; }
22 set { name = value; }
23 }
24
25 public Friend(string name)
26 {
27 this.name = name;
28 }
29 }
30
31 public class Friends : IEnumerable
32 {
33 private Friend[] friendarray;
34
35 public Friends()
36 {
37 friendarray=new Friend[]
38 {
39 new Friend("張三"),
40 new Friend("李四"),
41 new Friend("王五"),
42 };
43 }
44
45 //索引器
46 public Friend this[int index] => friendarray[index];
47
48 public int Count => friendarray.Length;
49
50 //實現IEnumerable<T>接口的方法
51 public IEnumerator GetEnumerator()
52 {
53 for (int index = 0; index < friendarray.Length; index++)
54 {
55 //在C# 2.0中,只需要使用下面的語句就可以實現一個迭代器
56 yield return friendarray[index];
57 }
58 }
59 }
60 }
這段代碼只用了一個yield return就完成了迭代器的實現,它作用就是在告訴編譯器,GetEnumerator方法不是一個普通的方法,而是實現迭代器的方法。當編譯器看到yield return 語句時,會在中間代碼中為我們生成了一個IEnumerator接口的對象。可以使用反射工具Reflector看一下。

由上圖可以看出,yield return語句其實是C#中提供的另一個語法糖(語法糖可以理解為C#提供的一種方便形式),它簡化了我們的迭代器源代碼,把具體而復雜的實現過程留給了編譯器去完成。