要使用foreach遍历类,必须让类实现IEnumerable接口,并且创建一个继承了Enumerator的类接收IEnumerable接口中GetEnumerator()方法的返回值.
那为什么数组可以直接用foreach遍历其中的数组的项呢?
因为在声明数组时.net已经隐式的让数组继承了IEnumertabel接口,并且创建了一个继承了IEnumramertor接口的类.(猜想)那么现在假设Person类有一个记忆功能,现在我想用foreach遍历person类读取,记忆中的数据,并把数据显示出来..
所以我先声明一个Person类,他有Name,Age,Memory字段,还有一个构造函数以及一个See方法,模拟人从外界得到记忆,并实现了IEnumerable接口,now,let us begin...class Person { private string name; private int age; private Listmemory = new List (); public string Name { get { return name; } } public int Age { get { return age; } } public string[] Memory { get { return memory.ToArray(); } } public Person(string name, int age) { this.name = name; this.age = age; } public void See(string data) { memory.Add(data); } public void See(string[] data) { memory.AddRange(data); } }
//现在如果我们要直接遍历p中的记忆并等到他的记忆,是没有办法的。
static void Main(string[] args) { //假设这些就是外界记忆 string[] data = { "sky", "ok", "mother", "father", "good", "wonderful" }; Person p = new Person("tom", 18); //将p记住了很多单词 p.See(data); //p在又一次记住了一个新的单词 p.See("wather"); //现在如果我们先要直接遍历p中的记忆并等到他的记忆,是没有办法的。 foreach (string item in p) { Console.WriteLine(item); } Console.ReadKey(); }
上面的代码会报错:
错误 1 “枚举数和迭代器.Person”不包含“GetEnumerator”的公共定义,因此 foreach 语句不能作用于“枚举数和迭代器.Person”类型的变量 C:\Users\Administrator.think-THINK\Documents\Visual Studio 2008\Projects\c sharp图解教程\枚举数和迭代器\Program.cs 30 13 枚举数和迭代器
所以我们要让Person类实现IEnumerable接口,IEnumerable接口中有且只有一个GetEnumerator方法,该方法返回IEnumerator类型参数,所以我们要创建了一个继承了IEnumramertor接口的类.用来接收GetEnumerator方放得返回值.
class Person:IEnumerable { private string name; private int age; private Listmemory = new List (); public string Name { get { return name; } } public int Age { get { return age; } } public string[] Memory { get { return memory.ToArray(); } } public Person(string name, int age) { this.name = name; this.age = age; } public void See(string data) { memory.Add(data); } public void See(string[] data) { memory.AddRange(data); } public IEnumerator GetEnumerator() { return new PersonEnumerator(memory); } } class PersonEnumerator : IEnumerator { List data = new List (); public PersonEnumerator(List list) { data = list; } private int positon = -1; public object Current { get { return data[positon]; } } public bool MoveNext() { positon++; return positon < data.Count; } public void Reset() { positon = -1; } }
在此运行代码
static void Main(string[] args) { //假设这些就是外界记忆 string[] data = { "sky", "ok", "mother", "father", "good", "wonderful" }; Person p = new Person("tom", 18); //将p记住了很多单词 p.See(data); //p在又一次记住了一个新的单词 p.See("wather"); //现在可行了,因为我们Person实现了IEnumerable接口,并且创建了一个用于接收IEnumramerable方法的继承IEnumerator的类 foreach (string item in p) { Console.WriteLine(item); } Console.ReadKey(); }
为什么数组可以直接用foreach遍历其中的item呢?
因为在声明数组时.net已经隐式的让数组继承了IEnumertabel接口,并且创建了一个继承了IEnumramertor接口的类.(猜想)现在我们来模拟下foreach是如何工作的
static void Main(string[] args) { string[] data = { "sky", "ok", "mother", "father", "good", "wonderful" }; Person p = new Person("tom", 18); p.See(data); p.See("wather"); //现在让我们模拟foreach是如何工作的 IEnumerable ieble = (IEnumerable)p; IEnumerator itor = ieble.GetEnumerator(); while (itor.MoveNext()) { string item = (string)itor.Current; Console.WriteLine(item); } Console.ReadKey(); }
结果跟上面的一样。。
完全的代码如下: View Code
1 static void Main(string[] args) 2 { 3 4 string[] data = { "sky", "ok", "mother", "father", "good", "wonderful" }; 5 Person p = new Person("tom", 18); 6 p.See(data); 7 p.See("wather"); 8 //现在如果我们先要直接遍历p中的记忆并等到他的记忆,是没有办法的。 9 //所以我们让person实现了Ienumrabel接口,并且创建一个继承了IEnumerator接口的类来接收IEnumerable方法的返回值,因此我们终于可以用foreach遍历p,得到p 的记忆 10 //为什么数组可以直接用foreach遍历其中的item呢? 11 //因为在声明数组时.net已经隐式的为数组让数组继承了IEnumertabel接口,并且创建了一个继承了IEnumramertor接口的类. 12 foreach (string item in p) 13 { 14 Console.WriteLine(item); 15 } 16 17 //现在让我们模拟foreach是如何工作的 18 //其实这里利用了多态的性质,因为Person继承了IEnumerable接口,所以可以通过接口变量来调用GetEnumerator()方法,这是有理由的...foreach不可能知道你传递过来的是数据是什么类型的,如果你直接用Person来调用,那下次传递过来的是Dog类.那foreach就不能工作了 19 IEnumerable ieble = (IEnumerable)p; 20 //为什么不用这个的原因,如上.. 21 //p.GetEnumerator(); 22 IEnumerator itor = ieble.GetEnumerator();//这里也利用了多态,为什么不用PersonEnumerator,而用接口变量,理由是一样的... 23 24 while (itor.MoveNext()) 25 { 26 string item = (string)itor.Current; 27 Console.WriteLine(item); 28 } 29 30 31 Console.ReadKey(); 32 } 33 } 34 //那么现在假设Person类有一个记忆功能,现在我想用foreach遍历person类读取,记忆中的数据,并把数据显示出来.. 35 //所以我先声明一个Person类,他有Name,Age,Memory字段,还有一个构造函数以及一个See方法,模拟人从外界得到记忆,并实现了IEnumerable接口,now,let us begin... 36 37 class Person:IEnumerable 38 { 39 private string name; 40 private int age; 41 private Listmemory = new List (); 42 public string Name 43 { 44 get 45 { 46 return name; 47 } 48 } 49 50 public int Age 51 { 52 get 53 { 54 return age; 55 } 56 } 57 58 public string[] Memory 59 { 60 get 61 { 62 return memory.ToArray(); 63 } 64 } 65 66 public Person(string name, int age) 67 { 68 this.name = name; 69 this.age = age; 70 } 71 72 public void See(string data) 73 { 74 memory.Add(data); 75 } 76 77 public void See(string[] data) 78 { 79 memory.AddRange(data); 80 } 81 82 public IEnumerator GetEnumerator() 83 { 84 return new PersonEnumerator(memory); 85 } 86 } 87 88 class PersonEnumerator : IEnumerator 89 { 90 List data = new List (); 91 public PersonEnumerator(List list) 92 { 93 data = list; 94 } 95 private int positon = -1; 96 public object Current 97 { 98 get 99 { 100 return data[positon]; 101 } 102 } 103 104 public bool MoveNext() 105 { 106 positon++; 107 return positon < data.Count; 108 } 109 110 public void Reset() 111 { 112 positon = -1; 113 } 114 }