zoukankan      html  css  js  c++  java
  • C#设计模式(15)——迭代器模式

    出处:https://www.cnblogs.com/wyy1234/

    C#设计模式(15)——迭代器模式

     

    1.迭代器模式介绍

      迭代器模式主要用于遍历聚合对象,将聚合对象的遍历行为分离出来,抽象为一个迭代器来负责。迭代器模式用的十分普遍,C#/JAVA等高级语言都对迭代器进行了封装用于遍历数组,集合,列表等,因为各种高级语言都对这种模式做了很好的封装,所以这种模式的使用价值远大于它的学习价值,MartinFlower甚至在网站上提出过撤销这个设计模式,所以这里不打算介绍迭代器模式的概念和原理,而是介绍C#中的迭代器模式应用:C#中的枚举器和迭代器。

    2、枚举器和可枚举类型

    先看一个简单的例子:

    复制代码
    1     static void Main(string[] args)
    2         {
    3             int[] arr = { 2,3,5,8};
    4             foreach (int item in arr)
    5             {
    6                 Console.WriteLine("item's Value is :{0}",item);
    7             }
    8             Console.ReadKey();
    9         }
    复制代码

      为什么数组能够通过foreach遍历呢?原因是数组实现了IEnumerable接口,IEumerable接口中只有一个成员方法:GetEnumerator(),这个方法返回一个枚举器对象,这个枚举器就是迭代器模式中的迭代器。枚举器可以依次返回请求中数组中的元素,它知道元素的顺序并跟踪元素在序列中的位置,然后返回请求的当前项,我们可以通过GetEnumerator方法获取枚举器对象。那么什么是枚举器呢?实现IEnumerator接口的类型就是枚举器,该接口有三个成员:

       current :获取当前位置元素

       MoveNext() :把枚举器位置前进到下一项,返回bool,表示位置是否有效(如果没有下一项返回false)

       Reset() :把位置重置为原始状态的位置(有索引是一般为-1)

    我们重新实现上边例子的foreach操作:

    复制代码
     1      static void Main(string[] args)
     2         {
     3             int[] arr = { 2,3,5,8};
     4             //获取arr的枚举器
     5             IEnumerator ie = arr.GetEnumerator();
     6             while (ie.MoveNext())
     7             {
     8                 int i = (int)ie.Current;
     9                 Console.WriteLine("item's value is:{0}",i);
    10             }
    11             Console.ReadKey();
    12         }
    复制代码

      知道了foreach内部是怎么运行的后,我们就可以自己实现一个可以用foreach遍历的类了:自定义的类要实现IEnumerable接口的GetEnumerator方法,这个方法返回一个枚举器(就是一个继承IEnumerator接口的类型),以遍历自定义颜色集合为例,代码如下:

    复制代码
       class Program
        {
            static void Main(string[] args)
            {
                ColorList colors = new ColorList();
                //foreach遍历自定义的类型
                foreach (var item in colors)
                {
                    Console.WriteLine(item);
                }
    
                Console.ReadKey();
    
            }
            
            /// <summary>
            /// 自定义类 ColorList实现IEnumerable接口
            /// </summary>
            public class ColorList : IEnumerable
            {
                //实现GetEnumerator接口方法
                public IEnumerator GetEnumerator()
                {
                    return new ColorEnumrator(new string[]{ "red", "blue", "green", "pink" });
                }
            }
            /// <summary>
            /// 自定义枚举器
            /// </summary>
            public class ColorEnumrator : IEnumerator
            {
                string[] _colors;
                //位置索引
                private int _position = -1;
                //枚举器构造方法
                public ColorEnumrator(string[] theColors)
                {
                    _colors = new string[theColors.Length];
                    for (int i = 0; i < theColors.Length; i++)
                    {
                        _colors[i] = theColors[i];
                    }
                }
                //获取当前项的值
                public object Current
                {
                    get
                    {
                        if (_position < 0 || _position > _colors.Length)
                        {
                            throw new Exception("超过边界了!");
                        }
                        return _colors[_position];
                    }
                }
                //指向下一项
                public bool MoveNext()
                {
                    if (_position<_colors.Length-1)
                    {
                        _position++;
                        return true;
                    }
                    return false;
                }
                //复位
                public void Reset()
                {
                    _position = -1;
                }
            }
        }
    复制代码

    程序运行结果如下:

    总结:可枚举类型是实现了IEnumerable接口的类,IEnumerable接口只有一个成员GetEnumerator方法,用于获取枚举器(实现IEnumerator接口的实例)。

    3.迭代器

      通过手动实现IEnumerable接口的IEnumerator方法我们已经可以实现自定义可枚举类型了,在C#2.0中提供了更简单的创建可枚举类型的方式:迭代器。我们使用迭代器时,不用我们自己去手动创建IEnumerator实例,编译器会自动帮我们生成IEnumerator内部的Current,MoveNext和Reset方法。使用迭代器上边的例子可以简化为:

    复制代码
        class Program
        {
            static void Main(string[] args)
            {
                ColorList colors = new ColorList();
                //foreach遍历自定义的ColorList类型
                foreach (var item in colors)
                {
                    Console.WriteLine(item);
                }
                Console.ReadKey();
    
               
            }
          
        }
        
        /// <summary>
        /// 自定义颜色集合,实现IEnumerable接口
        /// </summary>
        public class ColorList : IEnumerable
        {
            //实现GetEnumerator接口方法
            public IEnumerator GetEnumerator()
            {
                string[] colors= { "red", "green", "blue", "pink" };
                for (int i = 0; i < colors.Length; i++)
                {
                    //yield return的作用是指定下一项的内容
                    yield return colors[i];
                }
    
                //想反向遍历时可以这样写
                //for (int i = colors.Length-1; i >=0; i--)
                //{
                //    yield return colors[i];
                //}
            }
        }
    复制代码

      程序运行结果和手动写Enumerator的例子一致,我们可以看出使用迭代器来生成可枚举类型要简单很多,这并不是创建迭代器的过程简单了,而是微软让编译器帮我们自动生成了IEnumerator中的current,MoveNext(),Reset()等内容。

  • 相关阅读:
    001 云开发基础
    HttpClient 调用外部接口(简单实用)
    MD5加密(简单实现_可自行扩展)
    SAA C02考点梳理
    支配树
    CF1320E 题解
    dp套dp
    20210705模拟赛总结
    20210703模拟赛
    20210629模拟赛总结
  • 原文地址:https://www.cnblogs.com/frank0812/p/11281549.html
Copyright © 2011-2022 走看看