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()等内容。

  • 相关阅读:
    工作中遇到的java 内存溢出,问题排查
    java线上内存溢出问题排查步骤
    性能测试-java内存溢出问题排查
    164 01 Android 零基础入门 03 Java常用工具类01 Java异常 04 使用try…catch…finally实现异常处理 04 终止finally执行的方法
    163 01 Android 零基础入门 03 Java常用工具类01 Java异常 04 使用try…catch…finally实现异常处理 03 使用多重catch结构处理异常
    162 01 Android 零基础入门 03 Java常用工具类01 Java异常 04 使用try…catch…finally实现异常处理 02 使用try-catch结构处理异常
    161 01 Android 零基础入门 03 Java常用工具类01 Java异常 04 使用try…catch…finally实现异常处理 01 try-catch-finally简介
    160 01 Android 零基础入门 03 Java常用工具类01 Java异常 03 异常处理简介 01 异常处理分类
    159 01 Android 零基础入门 03 Java常用工具类01 Java异常 02 异常概述 02 异常分类
    158 01 Android 零基础入门 03 Java常用工具类01 Java异常 02 异常概述 01 什么是异常?
  • 原文地址:https://www.cnblogs.com/frank0812/p/11281549.html
Copyright © 2011-2022 走看看