在本身的對象裏實現IEnumerator和IEnumerable

平時工做中咱們常常用foreach來迭代一個集合。好比web

1 foreach (Student student in myClass)
2 3        Console.WriteLine(student);
4 5  

基本全部的集合都可以foreach,可是必需要實現IEnumerable接口。IEnumerable接口很簡單,就只有一個IEnumerator GetEnumerator() 方法。看這個方法的定義就知道,僅僅是公開了另外一個接口IEnumerator。而IEnumerator纔是真正的支持一個集合的迭代。IEnumerator有1個屬性和2個方法。ide

public object Current; 函數

public void Reset();this

public bool MoveNext();spa

只容許讀取集合的數據,而不容許修改。爲了詳細的講解,咱們來寫一個簡單的例子,就會一目瞭然。翻譯

首先咱們建立一個學生類Student以下:code

 

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 
 6 namespace IenumerableDemo
 7 {
 8     public class Student
 9     {
10         #region 私有變量
11 
12         private readonly string _id;
13         private string _firstname;
14         private string _lastname;
15 
16         #endregion
17         #region 屬性
18         public string ID { get { return _id; } }
19 
20         public string FirstName { get { return _firstname; } set { _firstname = value; } }
21 
22         public string LastName { get { return _lastname; } set { _lastname = value; } }
23 
24 
25         #endregion
26 
27         #region 構造函數
28 
29         public Student(string id, string firstname, string lastname)
30         {
31             this._id = id;
32 
33             this._firstname = firstname;
34 
35             this._lastname = lastname;
36         }
37 
38         #endregion
39         #region  重寫基類object方法
40 
41         public override string ToString()
42         {
43             return string.Format("{0} {1},ID:{2}", _firstname, _lastname, _id);
44         }
45 
46         public override bool Equals(object obj)
47         {
48             if (obj == null) return false;
49             if (Object.ReferenceEquals(this, obj)) return true;
50             if (this.GetType() != obj.GetType()) return false;
51 
52             Student objstudent = (Student)obj;
53             if (_id.Equals(objstudent._id)) return true;
54 
55             return false;
56         }
57 
58         public override int GetHashCode()
59         {
60             return _id.GetHashCode();
61         }
62         #endregion
63 
64     }
65 }
66 
67         

接下來咱們定義一個ClassList類來承載學生。讓咱們先忘記Ienmerable。這個類包含一個ArrayList字段_student,在構造函數中模擬3個學生。_student是私有的,不對外公開的。orm

 

 1 using System;
 2 using System.Collections;
 3 using System.Collections.Generic;
 4 using System.Linq;
 5 using System.Text;
 6 
 7 namespace IenumerableDemo
 8 {
 9     public class ClassList
10     {
11 
12         #region private Members
13 
14         private readonly string _id;
15 
16         private ArrayList _students;
17 
18         #endregion
19 
20         #region Properties
21         public string ID { get { return _id; } }
22         #endregion
23 
24         #region Constructors
25 
26         public ClassList(string id)
27         {
28 
29             this._id = id;
30             _students = new ArrayList() { new Student("12345", "John", "Smith"), new Student("09876", "Jane", "Doe"), new Student("76403", "Bob", "Johnson") };
31 
32         }
33 
34         #endregion
35 
36  
37     }
38 }

 

爲了讓對象支持foreach 迭代,ClassList類須要實現IEnumerable。由於咱們的student是存在ArrayList對象裏的,而ArrayList類已經實現了IEnumerable,咱們就可使用ArrayList類的Ienumerable。對象

1        public IEnumerator GetEnumerator()
2         {
3 
4             return (_students as IEnumerable).GetEnumerator();
5 
6         }

最終的代碼貼一下:blog

 1 using System;
 2 using System.Collections;
 3 using System.Collections.Generic;
 4 using System.Linq;
 5 using System.Text;
 6 
 7 namespace IenumerableDemo
 8 {
 9     public class ClassList:IEnumerable
10     {
11 
12         #region private Members
13 
14         private readonly string _id;
15 
16         private ArrayList _students;
17 
18         #endregion
19 
20         #region Properties
21         public string ID { get { return _id; } }
22         #endregion
23 
24         #region Constructors
25 
26         public ClassList(string id)
27         {
28 
29             this._id = id;
30             _students = new ArrayList() { new Student("12345", "John", "Smith"), new Student("09876", "Jane", "Doe"), new Student("76403", "Bob", "Johnson") };
31 
32         }
33 
34         #endregion
35 
36         public IEnumerator GetEnumerator()
37         {
38 
39             return (_students as IEnumerable).GetEnumerator();
40 
41         }
42     }
43 }

而後咱們調用看看使用ArrayList的Ienumerable效果:

 1 using System;
 2 using System.Collections;
 3 using System.Collections.Generic;
 4 using System.Linq;
 5 using System.Text;
 6 
 7 namespace IenumerableDemo
 8 {
 9     class Program
10     {
11         static void Main(string[] args)
12         {
13             ClassList myClass = new ClassList("History 204");
14 
15 
16             foreach (Student student in myClass)
17 
18                 Console.WriteLine(student);
19 
20 
21             Console.ReadLine();
22         }
23 
24 
25     }
26 
27 
28 }

看來仍是實現了效果。那麼接下來咱們看看自定義實現IEnumerable。實現IEnumerable其實只要實現IEnumerator接口就能夠了。

咱們建立咱們本身的一個自定義類ClassEnumerator 來實現IEnumerator來完成和上面相同的結果。這個類基本上就只是經過_students的索引來進行迭代,Reset()方法就是把索引設置爲-1.Current屬性來獲取當前的student,MoveNext()來跳到Current的下一個數據,並返回一個boolean來表示是否到了集合最後。

 1 using System;
 2 using System.Collections;
 3 using System.Collections.Generic;
 4 using System.Linq;
 5 using System.Text;
 6 
 7 namespace IenumerableDemo
 8 {
 9     public class ClassEnumerator : IEnumerator
10     {
11 
12         private ClassList _classList;
13 
14         private int _index;
15 
16         public ClassEnumerator(ClassList classList)
17         {
18             this._classList = classList;
19 
20             _index = -1;
21         }
22 
23         #region IEnumerator Members
24 
25         public void Reset()
26         {
27             this._index = -1;
28         }
29 
30         public object Current
31         {
32             get { return _classList.Students[_index]; }
33         }
34 
35         public bool MoveNext()
36         {
37             _index++;
38             if (_index >= _classList.Students.Count)
39                 return false;
40             else
41                 return true;
42 
43         }
44         #endregion
45 
46     }
47 }

最後修改咱們的ClassLst類:

 1 using System;
 2 using System.Collections;
 3 using System.Collections.Generic;
 4 using System.Linq;
 5 using System.Text;
 6 
 7 namespace IenumerableDemo
 8 {
 9     public class ClassList : IEnumerable
10     {
11 
12         #region private Members
13 
14         private readonly string _id;
15 
16         private ArrayList _students;
17 
18         #endregion
19 
20         #region Properties
21         public string ID { get { return _id; } }
22 
23         public ArrayList Students { get { return _students; } }
24         #endregion
25 
26         #region Constructors
27 
28         public ClassList(string id)
29         {
30 
31             this._id = id;
32             _students = new ArrayList() { new Student("12345", "John", "Smith"), new Student("09876", "Jane", "Doe"), new Student("76403", "Bob", "Johnson") };
33 
34         }
35 
36         #endregion
37 
38         public IEnumerator GetEnumerator()
39         {
40 
41             return (IEnumerator)new ClassEnumerator(this);
42 
43         }
44     }
45 }

可已看到仍是至關簡單的。運行結果和上面是同樣的。

 下來看看 foreach怎麼工做。

其實foreach只是語法糖,最終會被CLR翻譯成

1             IEnumerator enumerator = myClass.GetEnumerator();
2             while (enumerator.MoveNext())
3             {
4                 Console.WriteLine((Student)enumerator.Current);
5 
6             }

咱們能夠把foreach 換成這樣試一下,結果是同樣滴。

 1 using System;
 2 using System.Collections;
 3 using System.Collections.Generic;
 4 using System.Linq;
 5 using System.Text;
 6 
 7 namespace IenumerableDemo
 8 {
 9     class Program
10     {
11         static void Main(string[] args)
12         {
13             ClassList myClass = new ClassList("History 204");
14 
15 
16             //foreach (Student student in myClass)
17 
18             //    Console.WriteLine(student);
19 
20 
21             IEnumerator enumerator = myClass.GetEnumerator();
22             while (enumerator.MoveNext())
23             {
24                 Console.WriteLine((Student)enumerator.Current);
25 
26             }
27 
28             Console.ReadLine();
29         }
30 
31 
32     }
33 
34 
35 }
相關文章
相關標籤/搜索