面向对象的设计,要求为对象做到好的职责分离,每个对象只包括最少的职责,这样其与其他对象的联系也越少,降低了对象间的耦合度。职责分离需要对对象被分离的职责进行封装,并以抽象的方式建立起彼此之间的关系。在设计中,我们往往将这些可能变化的对象抽象为接口和抽象类,从而将原来的具体依赖改变为抽象依赖。
迭代器模式就是分离集合对象的职责的方法,其将集合对象存储数据(存储数据的类型、存储空间的大小、存储空间的分配等)和顺序访问数据这二种职责进行分离。
目的:
提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。
适用性:
访问一个聚合对象的内容而无需暴露它的内部表示。
支持对聚合对象的多种遍历。
为遍历不同的聚合结构提供一个统一的接口(即, 支持多态迭代)。
C#典型实现:
在.Net中,迭代器由IEnumerator接口所定义:












该接口提供了遍历集合元素的方法,其中主要的方法是MoveNext()。它将集合中的元素下标移到下一个元素。如果集合中没有元素,或已经移到了最后一个,则返回false。能够提供元素遍历的集合对象,在.Net中都实现了IEnumerator接口。
而.Net中的所有集合类则实现另一个接口IEnumerable,其定义如下:





GetEnumerator()方法是一个生成迭代器的工厂方法,在集合类的内部以内部类的方式定义一个实现了IEnumerator接口的迭代器类,并在GetEnumerator()方法中返回其迭代器类的一个实例。
下面是.Net中的ArrayList的实现示意类图:
其中,类ArrayListEnumeratorSimple的相关实现如下所示:
[Serializable]
private class ArrayListEnumeratorSimple : IEnumerator, ICloneable
{
// Methods
internal ArrayListEnumeratorSimple(ArrayList list)
{
this.list = list;
this.index = -1;
this.version = list._version;
this.currentElement = list;
}
public virtual bool MoveNext()
{
if (this.version != this.list._version)
{
throw new InvalidOperationException(Environment.GetResourceString(”InvalidOperation_EnumFailedVersion”));
}
if (this.index < (this.list.Count - 1))
{
this.index++;
this.currentElement = this.list[this.index];
return true;
}
this.currentElement = this.list;
this.index = this.list.Count;
return false;
}
public virtual void Reset()
{
if (this.version != this.list._version)
{
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));
}
this.currentElement = this.list;
this.index = -1;
}
// Properties
public virtual object Current
{
get
{
object obj1 = this.currentElement;
if (obj1 != this.list)
{
return obj1;
}
if (this.index == -1)
{
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumNotStarted"));
}
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumEnded"));
}
}
// Fields
private object currentElement;
private int index;
private ArrayList list;
private int version;
}
ArrayListEnumeratorSimple实现了IEnumerator接口,实现了MoveNext()、Current、Reset ()方法或属性。该类是一个私有类型,其构造函数则被internal修饰符限制。在自定义的构造函数中,传入的参数类型是ArrayList。正是通过 构造函数传递需要遍历的ArrayList对象,来完成MoveNext()、Current、Reset()等操作。
在ArrayList中,IEnumerable接口的GetEnumerator()方法实现代码如下:
public virtual IEnumerator GetEnumerator()
{
return new ArrayListEnumeratorSimple(this);
}
.Net2.0的实现:
由于在.Net2.0中对迭代器的实现提供了直接支持,所以其实现更加简单,并且不需要实现IEnumerable:






但.Net2.0的编译器最终会将其编译成类似典型实现的代码,只不过我们不需要再去手工实现IEnumerator接口。