博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

十六章:构建自定义集合(Part 2)

Posted on 2011-06-14 18:07  ritazhou  阅读(187)  评论(0编辑  收藏  举报

迭代器(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取消迭代。