玩转迭代器

迭代器概述

迭代器是可以返回相同类型的值的有序序列的一段代码。

迭代器可用作方法、运算符或 get 访问器的代码体。

迭代器代码使用 yield return 语句依次返回每个元素。yield break 将终止迭代。有关更多信息,请参见 yield。

可以在类中实现多个迭代器。每个迭代器都必须像任何类成员一样有唯一的名称,并且可以在 foreach 语句中被客户端代码调用,如下所示:foreach(int x in SampleClass.Iterator2){}

迭代器的返回类型必须为 IEnumerable、IEnumerator、IEnumerable<T> 或 IEnumerator<T>。

迭代器是使用在foreach中的集合。在C#2.0中使用迭代器创建一个用于foreach的集合,实现上比较简单:继承于IEumnerable,并实现GetEnumerator()。

首先这个集合要基于IEnumerable(可以使用泛型),下面先来实现一个非泛型版的迭代器。代码如下(非泛型代码示例来源于MSDN):

?

public class DaysOfTheWeek : System.Collections.IEnumerable

   {

     string[] m_Days = { "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" };

     public System.Collections.IEnumerator GetEnumerator()

     {

       for (int i = 0; i < m_Days.Length; i++)

       {

         yield return m_Days[i];

       }

     }

   }

   class TestDaysOfTheWeek

   {

     static void Main()

     {

       DaysOfTheWeek week = new DaysOfTheWeek();

       foreach (string day in week)

       {

         System.Console.Write(day + " ");

       }

       Console.Read();

     }

  }

操作结果是:

Sun Mon Tue Wed Thr Fri Sat

其中yied return关键字产生枚举元素

泛型版迭代器的实现代码如下:

?

static void Main(string[] args)

    {

      Stack<int> stack = new Stack<int>();

      stack.items = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

      foreach (int i in stack)

      {

        Console.WriteLine(i);

      }

      Console.Read();

   }

public class Stack<T> : IEnumerable<T>

  {

    public T[] items;

    public IEnumerator<T> GetEnumerator()

    {

      for (int i = 0; i < items.Length; i++)

      {

        yield return items[i];

      }

    }

    IEnumerator IEnumerable.GetEnumerator()

    {

      return GetEnumerator();

    }

}

运行结果如下:

1 2 3 4 5 6 7 8 9 10

其中G在实现泛型迭代器时我一直没有写IEnumerator IEnumerable.GetEnumerator()这个方法,所以编译器一直在给我报错,(猜想)这个方法应该IEnumerator<T>接口中的一个抽象方法。而这个方法中调用的GetEnumerator(),通过集成环境中的提示发现,实际上是上面写到的IEnumerator<T> GetEnumerator()这个泛型方法。

在自定义迭代器时,我们可以利用yield break关键字跳出循环。如上面的例子中,我们想只输出小于等于5的项,调整上面代码,如:

public class Stack<T> : IEnumerable<T>   {     public T[] items;

    public IEnumerator<T> GetEnumerator()     {

      for (int i = 0; i < items.Length; i++)       {        

        if ((Convert.ToInt32(items[i]) > 5))           yield break;

        yield return items[i];       }     }

    IEnumerator IEnumerable.GetEnumerator()     {       return GetEnumerator();     }   }

操作结果:

1 2 3 4 5

迭代器的机制:

  实际上迭代器只是在C#2.0中通过编译器一层额外处理的,用来简化创建可用于foreach的枚举集合的工作,从性能上没有什么变化。对于其生成的中间语言没有太多的变化。
实例:定义和使用命名迭代器

   class Class1   {     public IEnumerator GetEnumerator()     {       for (int i = 0; i < 10; i++)       {         yield return i;       }     }

    // 定义一个命名的迭代器,并可以提供参数     public IEnumerable MaxToMin(int min, int max)     {       for (int i = max; i >= min; i--)       {         yield return i;       }     }

    // 定义一个迭代器类型的属性,     public IEnumerable MinToMax     {       // this表示该类实例,因为该类实现了GetEnumerator(),它是可枚举的       get { yield return this; }     }

    public IEnumerable GetDescriptions()     {       yield return "this is my test";       yield return "class name is class1";       yield return "ktgu";     }   }

  static void Main(string[] args)   {          Class1 c = new Class1();

    foreach (int i in c)     {       Console.WriteLine(i);     }

    foreach (int i in c.MaxToMin(1, 10))     {       Console.WriteLine(i);     }

    foreach (int i in c.MinToMax)     {       Console.WriteLine(i);     }

    foreach (string s in c.GetDescriptions())     {       Console.WriteLine(s);     }    }

迭代效果及实现要点

1.迭代抽象:访问一个聚合对象的内容而无需暴露它的内部表示。

2.迭代多态:为遍历不同的集合结构提供一个统一的接口,从而支持同样的算法在不同的集合结构上进行操作。

3.迭代器的健壮性考虑:遍历的同时更改迭代器所在的集合结构,会导致问题。

适用性

1.访问一个聚合对象的内容而无需暴露它的内部表示。

2.支持对聚合对象的多种遍历。

3.为遍历不同的聚合结构提供一个统一的接口(即, 支持多态迭代)。

总结

Iterator模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明的访问集合内部的数据
参考: C#2.0-迭代器应用 http://cs.alienwave.cn/Topic/1347.aspx 迭代器(C# 编程指南) http://msdn2.microsoft.com/zh-cn/library/dscyy5s0(VS.80).aspx

时间: 2024-10-13 18:41:37

玩转迭代器的相关文章

Day4 - 迭代器&amp;生成器、装饰器、Json &amp; pickle 数据序列化、软件目录结构规范

---恢复内容开始--- 本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 需求:列表a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],要求把列表里的每个值加1 1 a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 2 b = [] 3 for i in a: 4 b.append(i+1) 5 a = b 6 print(a) 普通青

python3 迭代器与生成器

pythom3 迭代器与生成器 迭代器'''迭代器是python最强大的功能之一,是访问集合元素的一种方式.迭代器是一个可以记住遍历的位置对象迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问玩结束.迭代器只能往前不会后退.迭代器有两个基本方法:iter()和next().字符串,列表或元组对象都可用于创建迭代器: ''' list=[1,2,6,3] it=iter(list)#创建迭代器对象 print(next(it))#结果1 print(next(it))#结果2 print(

python之路系列-生成器和迭代器-景丽洋老师

返回顶部 楔子 假如我现在有一个列表l=['a','b','c','d','e'],我想取列表中的内容,有几种方式? 首先,我可以通过索引取值l[0],其次我们是不是还可以用for循环来取值呀? 你有没有仔细思考过,用索引取值和for循环取值是有着微妙区别的. 如果用索引取值,你可以取到任意位置的值,前提是你要知道这个值在什么位置. 如果用for循环来取值,我们把每一个值都取到,不需要关心每一个值的位置,因为只能顺序的取值,并不能跳过任何一个直接去取其他位置的值. 但你有没有想过,我们为什么可以

day16 迭代器和生成器

分页查找 #5.随意写一个20行以上的文件(divmod) # 运行程序,先将内容读到内存中,用列表存储. # l = [] # 提示:一共有多少页 # 接收用户输入页码,每页5条,仅输出当页的内容 def read_page(bk_list,n,endline=None): startline = 5 * (n-1) endline = endline+startline-1 if endline else startline + 4 # print(startline,endline) fo

Day4 - Python基础4 迭代器、装饰器、软件开发规范

Python之路,Day4 - Python基础4 (new版) 本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 孩子,我现在有个需求,看列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],我要求你把列表里的每个值加1,你怎么实现?你可能会想到2种方式 >>> a [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>

玩转Openstack之Nova中的协同并发(一)

玩转Openstack之Nova中的协同并发(一) 前不久参加了个Opnstack的Meetup,其中有一个来自EasyStack的大大就Nova中的协同并发做了一番讲解,有所感触,本想当天就总结一下,但是由于前段时间工作上比较忙,加上为了履行诺言每天几更的来写设计模式系列性文章,故而拖到今天才写此次的总结.好吧,其实归根结底还是自己太懒了,趁着闲时在补新番小笼包之类的.废话就此打住,开始正文. Python中协程的介绍 在此之前,先介绍下Python中的并发,在Python中,并发有三种,分别

python基础之迭代器协议和生成器

一 递归和迭代 略 二 什么是迭代器协议 1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代 (只能往后走不能往前退) 2.可迭代对象:实现了迭代器协议的对象(如何实现:对象内部定义一个__iter__()方法) 3.协议是一种约定,可迭代对象实现了迭代器协议,python的内部工具(如for循环,sum,min,max函数等)使用迭代器协议访问对象. 三 python中强大的for循环机制 for循环的本

Python--生成器与迭代器

生成器(generator) 在看生成器之前我们先来看一下列表生成式. 如果我们想得到一个12,22,32-- 102组成的列表,我们可以考虑下面的做法: 1 a=[x*x for x in range(1,11)] 2 print(a) 输出: ---------- [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] ---------- 这是Python的简洁的体现之一,我们可以用这种方式快速得到一个列表.其实他还有很多玩法: 1 import pprint 2 a

python基础-------迭代器,生成器,协程函数

1,迭代器协议: 1.1 迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代 (只能往后走不能往前退) 1.2. 可迭代对象:实现了迭代器协议的对象(如何实现:对象内部定义一个__iter__()方法) 1.3. 协议是一种约定,可迭代对象实现了迭代器协议,python的内部工具(如for循环,sum,min,max函数等)使用迭代器协议访问对象 2,迭代器: 1.1:为什么要用迭代器: 1.2 优点:迭代器提