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

  • 相关阅读:
    AX ERROR: Could not find my mock parent, most likely I am stale 不及格的程序员
    利用Segue在视图控制器间传值的问题 不及格的程序员
    Creating a Singleton Instance 不及格的程序员
    iPad 通知 UIKeyboardWillShowNotification 不会在keyBoard处在Undock状态下接到通知 不及格的程序员
    Why RootViewController's view is rotated Automatically by System when the app first loaded? 不及格的程序员
    如何弹出UIDatePicker最好 不及格的程序员
    jQuery开始做恶了 不及格的程序员
    what is the SEL,id and IMP,Class ,Method? 不及格的程序员
    Objectivec 字符串比较的陷井 不及格的程序员
    Unable to create any keyboard shortcuts after the iOS 6.1.3 update on iPad. 不及格的程序员
  • 原文地址:https://www.cnblogs.com/dairuiqing/p/4326693.html
Copyright © 2011-2022 走看看