C#基础知识---迭代器与Foreach语句

一、Foreach语句简介

在C# 1.0中我们经常使用foreach来遍历一个集合中的元素,然而如果一个集合要支持使用foreach语句来进行遍历,这个集合一般需要IEnumerableIEnumerable<T>接口

因为foreach是迭代语句,要使用foreach必须要有一个迭代器才行的,而IEnumerable接口中的IEnumerator GetEnumerator()方法是返回迭代器的。

在C# 1.0中,要获得迭代器一般需要实现IEnumerable接口中的GetEnumerator()方法,然而要实现一个迭代器就必须实现IEnumerator接口。

在C# 2.0中,提供 yield关键字来简化迭代器的实现。

foreach被编译后会调用GetEnumerator来返回一个迭代器。

 

二、C#1.0中实现迭代器

  1 using System;
  2 using System.Collections;
  3 
  4 namespace 迭代器Demo
  5 {
  6     class Program
  7     {
  8         static void Main(string[] args)
  9         {
 10             Friends friendcollection = new Friends();
 11             foreach (Friend f in friendcollection)
 12             {
 13                 Console.WriteLine(f.Name);
 14             }
 15 
 16             Console.Read();
 17         }
 18     }
 19 
 20     /// <summary>
 21     ///  朋友类
 22     /// </summary>
 23     public class Friend
 24     {
 25         private string name;
 26         public string Name
 27         {
 28             get { return name; }
 29             set { name = value; }
 30         }
 31         public Friend(string name)
 32         {
 33             this.name = name;
 34         }
 35     }
 36 
 37     /// <summary>
 38     ///   朋友集合
 39     /// </summary>
 40     public class Friends : IEnumerable
 41     {
 42         private Friend[] friendarray;
 43 
 44         public Friends()
 45         {
 46             friendarray = new Friend[]
 47             {
 48                 new Friend("张三"),
 49                 new Friend("李四"),
 50                 new Friend("王五")
 51             };
 52         }
 53 
 54         // 索引器
 55         public Friend this[int index]
 56         {
 57             get { return friendarray[index]; }
 58         }
 59 
 60         public int Count
 61         {
 62             get { return friendarray.Length; }
 63         }
 64 
 65         // 实现IEnumerable<T>接口方法
 66        public  IEnumerator GetEnumerator()
 67         {
 68             return new FriendIterator(this);
 69         }
 70     }
 71 
 72     /// <summary>
 73     ///  自定义迭代器,必须实现 IEnumerator接口
 74     /// </summary>
 75     public class FriendIterator : IEnumerator
 76     {
 77         private readonly Friends friends;
 78         private int index;
 79         private Friend current;
 80         internal FriendIterator(Friends friendcollection)
 81         {
 82             this.friends = friendcollection;
 83             index = 0;
 84         }
 85 
 86         #region 实现IEnumerator接口中的方法
 87         public object Current
 88         {
 89             get
 90             {
 91                 return this.current;
 92             }
 93         }
 94 
 95         public bool MoveNext()
 96         {
 97             if (index + 1 > friends.Count)
 98             {
 99                 return false;
100             }
101             else
102             {
103                 this.current = friends[index];
104                 index++;
105                 return true;
106             }
107         }
108 
109         public void Reset()
110         {
111             index = 0;
112         }
113 
114         #endregion 
115     }
116 }
View Code

 

三、C#2.0中实现迭代器

 1 namespace 简化迭代器的实现
 2 {
 3     class Program
 4     {
 5         static void Main(string[] args)
 6         {
 7             Friends friendcollection = new Friends();
 8             foreach (Friend f in friendcollection)
 9             {
10                 Console.WriteLine(f.Name);
11             }
12 
13             Console.Read();
14         }
15     }
16 
17     /// <summary>
18     ///  朋友类
19     /// </summary>
20     public class Friend
21     {
22         private string name;
23         public string Name
24         {
25             get { return name; }
26             set { name = value; }
27         }
28         public Friend(string name)
29         {
30             this.name = name;
31         }
32     }
33 
34     /// <summary>
35     ///   朋友集合
36     /// </summary>
37     public class Friends : IEnumerable
38     {
39         private Friend[] friendarray;
40 
41         public Friends()
42         {
43             friendarray = new Friend[]
44             {
45                 new Friend("张三"),
46                 new Friend("李四"),
47                 new Friend("王五")
48             };
49         }
50 
51         // 索引器
52         public Friend this[int index]
53         {
54             get { return friendarray[index]; }
55         }
56 
57         public int Count
58         {
59             get { return friendarray.Length; }
60         }
61 
62         // C# 2.0中简化迭代器的实现
63         public IEnumerator GetEnumerator()
64         {
65             for (int index = 0; index < friendarray.Length; index++)
66             {
67                 // 这样就不需要额外定义一个FriendIterator迭代器来实现IEnumerator
68                 // 在C# 2.0中只需要使用下面语句就可以实现一个迭代器
69                 yield return friendarray[index];
70             }
71         }
72     }
73 }
View Code

在上面代码中有一个yield return 语句,这个语句的作用就是告诉编译器GetEnumerator方法不是一个普通的方法,而是实现一个迭代器的方法。

当编译器看到yield return语句时,编译器知道需要实现一个迭代器,所以编译器生成中间代码时为我们生成了一个实现IEnumerator接口的内部类。

大家可以通过Reflector工具进行查看,下面是通过Reflector工具得到一张截图:

四、迭代器执行过程

 

注:本文参考http://www.cnblogs.com/zhili/archive/2012/12/02/Interator.html

 

posted on 2018-09-08 10:42  缘惜  阅读(1155)  评论(0编辑  收藏  举报