下面的代码示例演示如何实现自定义集合的 IEnumerable 和 IEnumerator 接口:
1 using System; 2 using System.Collections; 3 using System.Collections.Generic; 4 using System.Linq; 5 using System.Text; 6 using System.Threading.Tasks; 7 8 namespace ConsoleApplication1 9 { 10 public class Person 11 { 12 public Person(string fName, string lName) 13 { 14 this.firstName = fName; 15 this.lastName = lName; 16 } 17 18 public string firstName; 19 public string lastName; 20 } 21 22 public class People : IEnumerable 23 { 24 private Person[] _people; 25 public People(Person[] pArray) 26 { 27 _people = new Person[pArray.Length]; 28 29 for (int i = 0; i < pArray.Length; i++) 30 { 31 _people[i] = pArray[i]; 32 } 33 } 34 35 IEnumerator IEnumerable.GetEnumerator() 36 { 37 return (IEnumerator)GetEnumerator(); 38 } 39 40 public PeopleEnum GetEnumerator() 41 { 42 return new PeopleEnum(_people); 43 } 44 } 45 46 public class PeopleEnum : IEnumerator 47 { 48 public Person[] _people; 49 50 // Enumerators are positioned before the first element 51 // until the first MoveNext() call. 52 int position = -1; 53 54 public PeopleEnum(Person[] list) 55 { 56 _people = list; 57 } 58 59 public bool MoveNext() 60 { 61 position++; 62 return (position < _people.Length); 63 } 64 65 public void Reset() 66 { 67 position = -1; 68 } 69 70 object IEnumerator.Current 71 { 72 get 73 { 74 return Current; 75 } 76 } 77 78 public Person Current 79 { 80 get 81 { 82 try 83 { 84 return _people[position]; 85 } 86 catch (IndexOutOfRangeException) 87 { 88 throw new InvalidOperationException(); 89 } 90 } 91 } 92 } 93 94 95 class Program 96 { 97 static void Main(string[] args) 98 { 99 Person[] peopleArray = new Person[3] 100 { 101 new Person("John", "Smith"), 102 new Person("Jim", "Johnson"), 103 new Person("Sue", "Rabon"), 104 }; 105 106 People peopleList = new People(peopleArray); 107 foreach (Person p in peopleList) 108 Console.WriteLine(p.firstName + " " + p.lastName); 109 } 110 } 111 }
可枚举类型 → 实现IEnumerable接口,可以不需要直接实现这个接口,但必须有个GetEnumerator方法,返回值类型必须为IEnumerator类型,也就是第四点最后一段代码中接口注释的那种写法!
枚举数 → 实现IEnumerator接口,实现全部方法,首先是调用GetEnumerator返回一个类型为IEnumerator的枚举数,然后编译器会隐式的调用实现IEnumerator类中的方法和属性!
总结:所以实现foreach遍历,必须达到上面的两种条件才能进行遍历对象,他们可以写在一起也可以分开,最好是分开,进行职责分离,一个类干一件事总归是好事!也满足面向对象的单一指责设计原则。