zoukankan      html  css  js  c++  java
  • 玩转迭代器

    迭代器概述

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

    迭代器可用作方法、运算符或 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

  • 相关阅读:
    关于MFC库和CRT库冲突的分析
    C++ Traits技术
    C/C++的参数传递机制
    C++与正态分布
    前端JavaScript
    python 前端 css
    python 前端 html
    MySQL 数据库
    网络编程 生产者消费者模型 GiL

  • 原文地址:https://www.cnblogs.com/dairuiqing/p/4326693.html
Copyright © 2011-2022 走看看