枚举数与可枚举类型(笔记)

要使用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 List<string> memory = new List<string>();
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 List<string> memory = new List<string>();
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<string> data = new List<string>();
public PersonEnumerator(List<string> 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 List<string> memory = new List<string>();
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<string> data = new List<string>();
91 public PersonEnumerator(List<string> 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 }




原文地址:https://www.cnblogs.com/shysky77/p/2275547.html