迭代器(Iterators)
在学习迭代器之前,需要先了解一下foreach的内部工作方式。要对一个对象使用foreach进行循环的话该对象必须有GetEnumerator方法,该方法是在IEnumerable接口下的。该方法会返回一个IEnumerator的实例,所以必须有一个迭代器累实现IEnumerator接口。该接口中的主要有一个Current属性和一个MoveNext()方法。 在foreach遍历的时候,会用到该迭代器类。这就是迭代器接口。
假如某个类要使用foreach,就必须实现枚举模式,但是这个模式实现起来比较麻烦,因为它要维护一个内部状态机。所以C#2.0引入了迭代器的概念。C#编译器遇到迭代器时,会把内容扩展成枚举模式的CIL代码。
迭代器语法
它提供了迭代器接口(即IEnumerable<T>和IEnumerator<T>接口的组合)的一个快捷方式。迭代器方式和迭代器接口实现出来的CIL是一致的。
我们要添加对迭代器接口的支持。
Public class BinaryTree<T>:IEnumerable<T>
{
public IEumerator<T> GetEnumerator()
{
yield return First;
yield return Second;
}
//Because IEnumerator<T> derives from IEnumerator, so this function also required.
System.Collection.IEnumerator System.Collections.IEnumerator.GetEnumerator()
{
return GetEnumerator();
}
}
迭代器和状态
一个迭代器在foreach语句中首次被调用,它的状态就会在枚举器中初始化。GetEnumerator()就被调用,从而获取一个迭代器实例(Iterator引用)。之后foreach的每一次循环都会调用iterator实例上的MoveNext()方法。在迭代器内部,我们会用yield return生成一个值,并返回给foreach语句。在返回值之后,GetEnumerator()方法就停了,等到下一个MoveNext)的请求,继续执行到下一个yield return。这个过程直到迭代器中没有更多的yield return为止。
可以采用 yield break取消迭代。