C#基础—迭代器(Iterator)

1、引入迭代器

记得以前经常做到一些面试题,是关于要实现迭代器必须实现什么接口?其实,在C# 1.0里我们就经常用到foreach了,所以,只要支持foreach,那么这个类型就可以使用foreach
去遍历。那如何才能支持foreach 呢?

其实,答案都知道,要实现IEnumerable 或 IEnumerable<T>、IEnumerator 接口,因为foreach
需要迭代器的支持,而IEnumerable 接口中含有返回迭代器的 GetEnumerator 方法,对此,可以查看下MSDN 对 IEnumerable
的定义。所以,我们只要实现这个方法就可以使用foreach 来遍历我们需要的类型。

2、迭代器的使用

什么是迭代器?
简单的理解就是集合中的某个位置。我们先写个小Demo来认识下如何去实现一个自定义的迭代器:


  1 //1.首先定义一个需要实现foreach遍历的对象,我们假设为要遍历一群人
3 class Person
5 {
7   public string FirstName;
11   public string LastName;
15   public Person(string firstName, string lastName)
17   {
19     this.FirstName = firstName;
21     this.LastName = lastName;
23   }
25 }
26
29 //2. 定义一个那个我们要遍历的一群人集合,我们把这个类型叫:PersonList
31 class PersonList : IEnumerable
33 {
35   //其实操作的是Person的数组
37   private Person[] _personList;
41   public PersonList(Person[] PersonList)
43   {
45     this._personList = PersonList;
47   }
48
51   /// <summary>
53   ///用来遍历PersionList类的索引器,类似类数组
55   /// </summary>
57   /// <param name="index"></param>
59   /// <returns></returns>
61   public Person this[int index]
63   {
65     get
67     {
69       return this._personList[index];
71     }
73   }
74
77   /// <summary>
79   ///一般集合也都有一个Count,我们也实现下
81   /// </summary>
83   public int Count
85   {
87     get
89     {
91       return this._personList.Length;
93     }
95   }
96
99   /// <summary>
101   ///这个是返回迭代器的方法,必须要实现的
103   /// </summary>
105   /// <returns></returns>
107   public IEnumerator GetEnumerator()
109   {
111     return (new PersonIterator(this)); //把当前自定义的集合传给迭代器进行遍历功能的实现,并返回迭代器对象
113   }
115 }
116
119 //3.定义一个自定义的迭代器,我们假设叫 PersonIterator,实现迭代器需要实现 System.Collection.IEnumerator 接口
121 class PersonIterator : IEnumerator
123 {
125   //要遍历的自定义对象集合,传入迭代器进行遍历
127   private readonly PersonList _personList;
131   //当前位置的索引
133   private int _position = -1;
134
137   public PersonIterator(PersonList personList)
139   {
141     this._personList = personList;
143   }
144
147   #region自定义迭代器必须要实现的IEnumerator中的几个方法和属性
151   public object Current
153   {
155     get
157     {
159       try
161       {
163         return this._personList[this._position];
165       }
167       catch(IndexOutOfRangeException)
169       {
171         throw new IndexOutOfRangeException();
173       }
175     }
177   }
178
181   public bool MoveNext()
183   {
185     this._position++;
187     return (this._position < this._personList.Count);
189   }
190
193   public void Reset()
195   {
197     this._position = -1;
199   }
203 #endregion
207 }
208
209
210
211 class Program
213 {
215   static void Main(string[] args)
217   {
219     Person[] personArray = new Person[2]
221     {
223       new Person("三", "张"),
225       new Person("四", "李")
227     };
231    //测试
233    PersonList pList = new PersonList(personArray);
235    foreach (Person p in pList)
237    {
239       Console.WriteLine("遍历的姓名: {0} {1}", p.FirstName, p.LastName);
241   }
242
245    Console.Read();
247 }
249 }

程序输出:

遍历的姓名:三 张

遍历的姓名:四 李

至此,我们在梳理下实现的步骤:

(1).定义要遍历的对象 Person

(2).定义要遍历的对象集合类 PersonList 实现 IEnumerable
接口,主要实现 GetEnumerator()方法,以便于返回一个迭代器对象。

(3).定义一个自定义的迭代器类 PersonIterator 实现
IEnumerator 接口,主要实现该接口中定义的方法和属性。

整个迭代器的实现过程略微显得复杂,如果每次都这样实现,的确感觉不太理想,因此C# 2.0
为我们提供了语法糖:yield return。让我们来看看实现的过程有哪些简化的呢?由于篇幅原因,我只提供了修改的地方:


 1 ///// <summary>
2 ///// 这个是返回迭代器的方法,必须要实现的
3 ///// </summary>
4 ///// <returns></returns>
5 //public IEnumerator GetEnumerator()
6 //{
7 //   return (new PersonIterator(this)); //把当前自定义的集合传给迭代器进行遍历功能的实现,并返回迭代器对象
8 //}
9
10
11 /// <summary>
12 ///这个是返回迭代器的方法,必须要实现的, C# 2.0 的yield return
13 /// </summary>
14 /// <returns></returns>
15 public IEnumerator GetEnumerator()
16 {
17   for (var i = 0; i < this._personList.Length; i++)
18   {
19     yield return this._personList[i];
20   }
22 }

这样我们就省去了第三步去实现IEnumerator来构造一个迭代器类,但是编译器的工作还是不会少的,当编译器看到
yield return 时会自动为我们实现IEnumerator 接口,有兴趣的同仁可以查看下最后编译后的代码,在此不再敖述。

3、迭代器的执行过程

对于迭代器的执行过程,大家可以调试测试,这里直接引用下园子里大神的图片做个演示了:

至此,迭代器先谈这么多了,至于迭代器的延迟计算,我们到Linq 中再谈,欢迎交流!

C#基础—迭代器(Iterator),布布扣,bubuko.com

时间: 2024-10-22 19:24:02

C#基础—迭代器(Iterator)的相关文章

java基础-迭代器(Iterator)与增强for循环

java基础-迭代器(Iterator)与增强for循环 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Iterator迭代器概述 Java中提供了很多个集合,它们在存储元素时,采用的存储方式不同.我们需要取出这些集合中的元素,可通过一种通用的方式来完成. Collection集合元素的通用获取方式:在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就在取出来.一直把集合中所有的元素全部取出.这种取出方式专业术语称为迭代.换句话说,迭代

java基础知识5--集合类(Set,List,Map)和迭代器Iterator的使用

写的非常棒的一篇总结: http://blog.csdn.net/speedme/article/details/22398395#t1 下面主要看各个集合如何使用迭代器Iterator获取元素: 1.list使用迭代器Iterator public class testArrayList { public static void main(String args[]) { f1(); f2(); } public static void f1(){ List<String> strList

C++迭代器 iterator

1. 迭代器(iterator)是一中检查容器内元素并遍历元素的数据类型.(1) 每种容器类型都定义了自己的迭代器类型,如vector:vector<int>::iterator iter;这条语句定义了一个名为iter的变量,它的数据类型是由vector<int>定义的iterator类型.(2) 使用迭代器读取vector中的每一个元素:vector<int> ivec(10,1);for(vector<int>::iterator iter=ivec.

ES6中的迭代器(Iterator)和生成器(Generator)

前面的话 用循环语句迭代数据时,必须要初始化一个变量来记录每一次迭代在数据集合中的位置,而在许多编程语言中,已经开始通过程序化的方式用迭代器对象返回迭代过程中集合的每一个元素 迭代器的使用可以极大地简化数据操作,于是ES6也向JS中添加了这个迭代器特性.新的数组方法和新的集合类型(如Set集合与Map集合)都依赖迭代器的实现,这个新特性对于高效的数据处理而言是不可或缺的,在语言的其他特性中也都有迭代器的身影:新的for-of循环.展开运算符(...),甚至连异步编程都可以使用迭代器 本文将详细介

C++迭代器 iterator【转】

1. 迭代器(iterator)是一中检查容器内元素并遍历元素的数据类型.(1) 每种容器类型都定义了自己的迭代器类型,如vector:vector<int>::iterator iter;这条语句定义了一个名为iter的变量,它的数据类型是由vector<int>定义的iterator类型.(2) 使用迭代器读取vector中的每一个元素:vector<int> ivec(10,1);for(vector<int>::iterator iter=ivec.

STL之迭代器(iterator)

1 头文件 所有容器有含有其各自的迭代器型别(iterator types),所以当你使用一般的容器迭代器时,并不需要含入专门的头文件.不过有几种特别的迭代器,例如逆向迭代器,被定义于<iterator>中. 2 迭代器类型 迭代器共分为五种,分别为: Input iterator.Output iterator.Forward iterator.Bidirectional iterator.Random access iterator. 2.1 Input(输入)迭代器 只能一次一个向前读取

设计模式 - 迭代器模式(iterator pattern) Java 迭代器(Iterator) 详解

迭代器模式(iterator pattern) Java 迭代器(Iterator) 详解 本文地址: http://blog.csdn.net/caroline_wendy 参考迭代器模式(iterator pattern): http://blog.csdn.net/caroline_wendy/article/details/35254643 Java的标准库(util)中包含迭代器接口(iterator interface), import java.util.Iterator; 继承(

用struts2标签如何从数据库获取数据并在查询页面显示。最近做一个小项目,需要用到struts2标签从数据库查询数据,并且用迭代器iterator标签在查询页面显示,可是一开始,怎么也获取不到数据,想了许久,最后发现,是自己少定义了一个变量,也就是var变量。

最近做一个小项目,需要用到struts2标签从数据库查询数据,并且用迭代器iterator标签在查询页面显示,可是一开始,怎么也获取不到数据,想了许久,最后发现,是自己少定义了一个变量,也就是var变量.<s:iterator>标签有一个value属性,用来存放在Action类的方法中存数据的list集合,还有一个id,好像是说指定集合的索引的意思,就是给list集合遍历出来的每个对象加上一个数字标签,反正我是这么理解的,没用过.还有一个很重要,就是var变量,我在s:iterator按ctr

迭代器Iterator的底层实现原理

第一步:没有接口的迭代器简单实现原理 1 package com.bjsxt.xiaofei; 2 /** 3 * 迭代器底层原理 4 * 方法: 5 * hasNext() 6 * next() 7 * remove() 8 * @ClassName: MyAarryList 9 * @Description: TODO(这里用一句话描述这个类的作用) 10 * @author 尚晓飞 11 * @date 2014-7-29 下午7:06:09 12 * 13 */ 14 public cl