hoyong

导航

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

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

要使用foreach遍历类,必须让类实现IEnumerable接口,并且创建一个继承了Enumerator的类接收IEnumerable接口中GetEnumerator()方法的返回值.

 

那为什么数组可以直接用foreach遍历其中的数组的项呢?
因为在声明数组时.net已经隐式的让数组继承了IEnumertabel接口,并且创建了一个继承了IEnumramertor接口的类.(猜想)

那么现在假设Person类有一个记忆功能,现在我想用foreach遍历person类读取,记忆中的数据,并把数据显示出来..
所以我先声明一个Person类,他有Name,Age,Memory字段,还有一个构造函数以及一个See方法,模拟人从外界得到记忆,并实现了IEnumerable接口,

 

now,let us begin...

 

class Person
    {
       
privatestring name;
        
privateint age;
       
private List<string> memory = new List<string>();
       
publicstring Name
        {
           
get
            {
               
return name;
            }
        }

       
publicint Age
        {
           
get
            {
               
return age;
            }
        }

       
publicstring[] Memory
        {
           
get
            {
               
return memory.ToArray();
            }
        }

       
public Person(string name, int age)
        {
            
this.name = name;
           
this.age = age;
        }

       
publicvoid See(string data)
        {
            memory.Add(data);
        }

       
publicvoid See(string[] data)
        {
            memory.AddRange(data);
        }
    }

 

 

 //现在如果我们要直接遍历p中的记忆并等到他的记忆,是没有办法的。

 staticvoid 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
    {
       
privatestring name;
       
privateint age;
       
private List<string> memory = new List<string>();
       
publicstring Name
        {
           
get
            {
               
return name;
            }
        }

       
publicint Age
        {
           
get
            {
               
return age;
            }
        }

       
publicstring[] Memory
        {
           
get
            {
               
return memory.ToArray();
            }
        }

        
public Person(string name, int age)
        {
           
this.name = name;
           
this.age = age;
        }

       
publicvoid See(string data)
        {
            memory.Add(data);
        }

       
publicvoid See(string[] data)
        {
            memory.AddRange(data);
        }

       
public IEnumerator GetEnumerator()
        {
           
returnnew PersonEnumerator(memory); //将需要遍历的东东作为参数传入, memory;
        }

    }

    
class PersonEnumerator : IEnumerator //定义类PersonEnumerator, 作为枚举器
    {
        List<
string> data = new List<string>();
       
public PersonEnumerator(List<string> list)
        {
            data = list;
        }
       
privateint positon = -1;
       
publicobject Current
        {
           
get
            {
               
return data[positon];
            }
        }

       
publicbool MoveNext()
        {
            positon++;
           
return positon < data.Count;
        }

       
publicvoid Reset()
        {
            positon = -
1;
        }
    }

说明: 复制代码

在此运行代码

说明: 复制代码

staticvoid 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是如何工作的

说明: 复制代码

staticvoid 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();
        }

说明: 复制代码

结果跟上面的一样。。

完全的代码如下

说明: http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif

说明: 复制代码

  1staticvoid 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; //将实例对象P转为IEnumerator接口类型赋给变更ieble, 以便用接口类型变量调用GetEnumerator(), 避免后续用实例对象P调用GetEnumerator(), 原因如18行描述.
 20       //为什么不用这个的原因,如上..
 21       //p.GetEnumerator();
 22             IEnumerator itor = ieble.GetEnumerator();//这里也利用了多态,为什么不用PersonEnumerator,而用接口变量,理由是一样的...
 23//21行程序调用流程ieble.GetEnumerator()->构造函数p. PersonEnumerator(memory), 返回PersonEnumerator类型实例对象, 并隐式转为IEnumerator接口类型, 赋值给IEnumerator接口类型变量itor.以便后期程序可通过itor调用PersonEnumerator类型中的方法, MoveNext(), Current(), Reset(), 也避免后续用返回PersonEnumerator类型实例对象调用PersonEnumerator类型中的方法, MoveNext(), Current(), Reset(); 原因如18行描述
 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         privatestring name;
 40         privateint age;
 41         private List<string> memory = new List<string>();
 42         publicstring Name
 43         {
 44             get
 45             {
 46                 return name;
 47             }
 48         }
 49
 50         publicint Age
 51         {
 52             get
 53             {
 54                 return age;
 55             }
 56         }
 57
 58         publicstring[] 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         publicvoid See(string data)
 73         {
 74             memory.Add(data);
 75         }
 76
 77         publicvoid See(string[] data)
 78         {
 79             memory.AddRange(data);
 80         }
 81
 82         public IEnumerator GetEnumerator()
 83         {
 84             returnnew PersonEnumerator(memory); //将需要遍历的东东作为参数传入构造函数并初始化枚举器,memory;
 85         }
 86     }
 87
 88     class PersonEnumerator : IEnumerator   //定义类PersonEnumerator, 作为枚举器
 89     {
 90         List<string> data = new List<string>();
 91         public PersonEnumerator(List<string> list)
 92         {
 93             data = list;
 94         }
 95         privateint positon = -1;
 96         publicobject Current
 97         {
 98             get
 99             {
100                 return data[positon];
101             }
102         }
103
104         publicbool MoveNext()
105         {
106             positon++;
107             return positon < data.Count;
108         }
109
110         publicvoid Reset()
111         {
112             positon = -1;
113         }
114     }

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 



来自为知笔记(Wiz)



附件列表

 

posted on 2016-04-22 21:09  hoyong  阅读(636)  评论(0编辑  收藏  举报