C#學習之自定義類實現foreach


本人初學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方法的方式,這個留到下一篇文章來說。謝謝!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM