本人初學C#,本文僅供個人整理思路用,那里說得不對,請大家多多指教,萬分感激!
本文目的:通過實現 IEnumerable 接口,使得自定義類能使用foreach語句來遍歷自身元素
前提知識:數組可以被foreach語句遍歷數組中的元素,原因是所有數組的基類都是System.Array ,而System.Array 類實現了IEnumerable接口,可以通過GetEnumerator方法按需提供一個叫做枚舉數(enumerator)的對象,枚舉數可以依次返回請求的數組的元素。 (注:C#里面的枚舉數,也就是枚舉器,類似於C++中的迭代器,而C#中的迭代器是另外一個意思。不知我這樣理解對否?)
第一部分:通過繼承IEnumerable接口實現foreach語句
第一步:創建Person類
View Code
1 public class Person
2 {
3 string Name;
4 int Age;
5
6 public Person(string name, int age)
7 {
8 Name = name;
9 Age = age;
10 }
11
12 public override string ToString()
13 {
14 return "Name: " + Name + "\tAge: " + Age;
15 }
16 }
第二步:創建PeopleEnum類,該類繼承IEnumerator接口,實現IEnumerator接口里的MoveNext、Reset方法和Current屬性
View Code
1 public class PeopleEnum : IEnumerator
2 {
3 private Person[] _people;
4 int position = -1;
5
6 public PeopleEnum(Person[] list)
7 {
8 _people = list;
9 }
10
11 public bool MoveNext()
12 {
13 position++;
14 return (position < _people.Length);
15 }
16
17 public void Reset()
18 {
19 position = -1;
20 }
21
22 public object Current
23 {
24 get
25 {
26 return _people[position];
27 }
28 }
29
30 }
第三步: 創建People類,該類繼承IEnumerable接口,實現了GetEnumerator方法,GetEnumerator方法的作用是獲取枚舉數(返回值是IEnumerator類型的,就是枚舉數的類型),在這里是通過返回PeopleEnum類的一個實例來取得枚舉數。
View Code
1 public class People : IEnumerable
2 {
3 private Person[] _people;
4 public People(Person[] pArray)
5 {
6 _people = new Person[pArray.Length];
7 for (int i = 0; i < pArray.Length; i++)
8 {
9 _people[i] = pArray[i];
10
11 }
12 }
13
14 public IEnumerator GetEnumerator()
15 {
16 return new PeopleEnum(_people);
17 }
18 }
第四步:People類實現了接口IEnumerable接口,所以People類的實例就能使用foreach來遍歷自身元素。主函數測試代碼如下:
1 class Program
2 {
3 static void Main(string[] args)
4 {
5 Person[] persons = new Person[]
6 {
7 new Person("aaa", 20),
8 new Person("bbb", 21),
9 new Person("ccc", 22)
10 };
11
12 People peopleList = new People(persons);
13
14 foreach (var item in peopleList)
15 {
16 System.Console.WriteLine(item);
17 }
18
19 System.Console.ReadKey();
20 }
21 }
輸出如下
第二部分:foreach實現的本質
第一部分里的第二步創建PeopleEnum類,並實現里其繼承的IEnumerator接口里的MoveNext、Reset方法和Current屬性,其實,該類已經具備了遍歷自身元素的條件了。
把主函數里的測試的代碼改成如下,運行-》輸出,結果是一樣的
View Code
1 class Program
2 {
3 static void Main(string[] args)
4 {
5 Person[] persons = new Person[]
6 {
7 new Person("aaa", 20),
8 new Person("bbb", 21),
9 new Person("ccc", 22)
10 };
11
12 while (peopleEnum.MoveNext())
13 {
14 System.Console.WriteLine(peopleEnum.Current);
15 }
16
17 System.Console.ReadKey();
18 }
19 }
但是不能使用foreach語句,為什么呢?因為使用foreach語句類必須提供GetEnumerator方法獲取該類的枚舉數,然后編譯器通過這個枚舉數來調用IEnumerator接口里的 MoveNext、Reset方法和Current屬性實現對類元素的遍歷。
給PeopleEnum類添加一個GetEnumerator方法
1 public IEnumerator GetEnumerator()
2 {
3 return this;
4 }
主函數測試代碼改成如下:
1 class Program
2 {
3 static void Main(string[] args)
4 {
5 Person[] persons = new Person[]
6 {
7 new Person("aaa", 20),
8 new Person("bbb", 21),
9 new Person("ccc", 22)
10 };
11
12
13 PeopleEnum peopleEnum = new PeopleEnum(persons);
14
15 foreach (var item in peopleEnum)
16 {
17 System.Console.WriteLine(item);
18
19 }
20
21 System.Console.ReadKey();
22 }
23 }
運行,成功!
結論:一個類想要實現foreach,就得提供GetEnumerator方法獲取該類的枚舉數(就是返回一個IEnumerator接口類型的變量)。實現GetEnumerator方法(或者稱為獲取枚舉數)的方式有很多種,本文采用了實現IEnumerable接口的方式(本質上也就是實現IEnumerator接口,只不過把GetEnumerator方法挪出去了而已)。其他還有例如通過迭代器來實現GetEnumerator方法的方式,這個留到下一篇文章來說。謝謝!
