一、什么是迭代器
迭代器(iterator)有时又称游标(cursor)是程序设计的软件设计模式,可在容器(container,例如链表或阵列)上遍访的接口,设计人员无需关心容器的内容。 迭代器模式是设计模式中行为模式(Behavioral pattern)的一个例子,他是一种简化对象间通讯的模式,也是一种非常容易理解和使用的模式。简单来说,迭代器模式使得你能够获取到序列中的所有元素而不用关心是其类型是array,list,linked list或者是其他什么序列结构。这一点使得能够非常高效的构建数据处理通道(data pipeline)--即数据能够进入处理通道,进行一系列的变换,或者过滤,然后得到结果。事实上,这正是LINQ的核心模式。
在.NET中,迭代器模式被IEnumerator和IEnumerable及其对应的泛型接口所封装。如果一个类实现了IEnumerable接口,那么就能够被迭代;调用GetEnumerator方法将返回IEnumerator接口的实现,它就是迭代器本身。迭代器类似数据库中的游标,他是数据序列中的一个位置记录。迭代器只能向前移动,同一数据序列中可以有多个迭代器同时对数据进行操作。迭代器的本质就是一个访问数据访问通道。
在C#1中已经内建了对迭代器的支持,那就是foreach语句。使得能够进行比for循环语句更直接和简单的对集合的迭代,编译器会将foreach编译来调用GetEnumerator和MoveNext方法以及Current属性,如果对象实现了IDisposable接口,在迭代完成之后会释放迭代器。但是在C#1中,实现一个迭代器是相对来说有点繁琐的操作。C#2使得这一工作变得大为简单,节省了实现迭代器的不少工作。
二、迭代器实现
1、1.0以前的实现
class Program { static void Main(string[] args) { Friends friendcollection = new Friends(); foreach (Friend f in friendcollection) { Console.WriteLine(f.Name); } Console.Read(); } } /// <summary> /// 朋友类 /// </summary> public class Friend { private string name; public string Name { get { return name; } set { name = value; } } public Friend(string name) { this.name = name; } } /// <summary> /// 朋友集合 /// </summary> public class Friends : IEnumerable { private Friend[] friendarray; public Friends() { friendarray = new Friend[] { new Friend("张三"), new Friend("李四"), new Friend("王五") }; } public Friend this[int index] { get { return friendarray[index]; } } public int Count { get { return friendarray.Length; } } // 实现IEnumerable<T>接口方法 public IEnumerator GetEnumerator() { return new FriendIterator(this); } } /// <summary> /// 自定义迭代器,必须实现 IEnumerator接口 /// </summary> public class FriendIterator : IEnumerator { private readonly Friends friends; private int index; private Friend current; internal FriendIterator(Friends friendcollection) { this.friends = friendcollection; index = 0; } #region 实现IEnumerator接口中的方法 public object Current { get { return this.current; } } public bool MoveNext() { if (index + 1 > friends.Count) { return false; } else { this.current = friends[index]; index++; return true; } } public void Reset() { index = 0; } #endregion }