博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
枚举数与可枚举类型(笔记)
阅读量:5064 次
发布时间:2019-06-12

本文共 8006 字,大约阅读时间需要 26 分钟。

要使用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
memory = 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 List
memory = 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 List
memory = 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 }
 

转载于:https://www.cnblogs.com/shysky77/archive/2011/12/04/2275547.html

你可能感兴趣的文章
ubuntu server 安装
查看>>
安装和卸载C#写的 windows service
查看>>
XIB做适配(二)
查看>>
Spring依赖注入:注解注入总结
查看>>
卸载 linux http
查看>>
log4j2 使用
查看>>
MFC的两个问题
查看>>
我想在 2012 储备的技术
查看>>
利用WindowsPhone7_SDK_Full.rar_for_xp,在xp下安装sdk,部署xap软件的教程
查看>>
那些我希望在一开始使用 Zsh(oh-my-zsh) 时就知道的
查看>>
macos port总结
查看>>
C/C++内存分配
查看>>
TCP的三次握手(建立连接)和四次挥手(关闭连接)
查看>>
[SDOI2017]数字表格
查看>>
某考试 T3 C
查看>>
AtCoder - 3939 Strange Nim
查看>>
asp.net mvc 接入阿里大于 短信验证码发送
查看>>
钟国晨160809323 (作业9)
查看>>
简单购物放大镜分享
查看>>
ROS学习(九)—— rqt_console 和 roslaunch
查看>>