zoukankan      html  css  js  c++  java
  • 【c#迭代器】

    在.NET中,迭代器模式被IEnumerator和IEnumerable及其对应的泛型接口所封装。如果一个类实现了IEnumerable接口,那么就能够被迭代;调用GetEnumerator方法将返回IEnumerator接口的实现,它就是迭代器本身。迭代器类似数据库中的游标,他是数据序列中的一个位置记录。迭代器只能向前移动,同一数据序列中可以有多个迭代器同时对数据进行操作。

    以一个手动迭代器为例子,进行详解迭代器:假如我们有一个集合添加“我,爱,的,是,c#”五个字母,那么输出时想从第三个开始输出,结果既是“是,c#,我,爱,的”,该怎么实现?迭代器就登场了......

            /// <summary>
            /// 主题:C#扫盲之迭代器
            /// 时间:2013-1-4 20:33:50
            /// 描述:利用迭代器输出字符串,从自己编写到优化
            /// 作者:白宁超
            /// </summary>
            /// <param name="args"></param>

    Sample类的迭代及创建如下:

      /// <summary>
        /// 主题:类的迭代输出初始化字符串
        /// 时间:2013-1-4 20:40:15
        /// 描述:通过创建Sample,实现字符串从第三个数打印出
        /// 作者:白宁超
        /// </summary>
         class Sample:IEnumerable
        {
            public  Object[] values;               //定义对象作为集合参数
            public  int starting;           //定义迭代起始点
            public Sample(Object[] values, Int32 starting) //构造方法
            {
                this.values = values;
                this.starting = starting;
            }
            // 摘要:返回一个循环访问集合的枚举器。
            // 返回结果:可用于循环访问集合的 System.Collections.IEnumerator 对象。
            public IEnumerator GetEnumerator()      
            {
                return new IterationSample(this);
            }
        }
    

     IterationSample迭代如下:为Sample类GetEnumerator方法提供返回值

    /// <summary>
         /// 主题:构造类的返回值
        /// 时间:2013-1-4 20:41:49
         /// 描述: IterationSample类来实现迭代器本身,通过GetEnumerator方法返回集合值
        /// 作者:白宁超
        /// </summary>
        class IterationSample : IEnumerator
        {
            Sample parent;//迭代的对象  
            int position;//当前游标的位置 
            internal IterationSample(Sample parent)
            {
                this.parent = parent;
                position = -1;// 数组元素下标从0开始,初始时默认当前游标设置为 -1,即在第一个元素之前, 
            }
            //获取集合中的当前元素
            public object Current
            {
                get
                {
                    if (position == -1 || position == parent.values.Length)//第一个之前和最后一个自后的访问非法 
                    {
                        throw new InvalidOperationException();
                    }
                    int index = position + parent.starting;//考虑自定义开始位置的情况  
                    index = index % parent.values.Length;
                    return parent.values[index];
                }
            }
            //将枚举数推进到集合的下一个元素
            public bool MoveNext()
            {
                if (position != parent.values.Length) //判断当前位置是否为最后一个,如果不是游标自增 
                {
                    position++;
                }
                return position < parent.values.Length;
            }
            //将枚举数设置为其初始位置,该位置位于集合中第一个元素之前。
            public void Reset()
            {
                position = -1;//将游标重置为-1  
            }
        }
    
     /// <summary>
            /// 主题:C#扫盲之迭代器
            /// 时间:2013-1-4 20:33:50
            /// 描述:利用迭代器输出字符串,从自己编写到优化
            /// 作者:白宁超
            /// </summary>
            /// <param name="args"></param>
            static void Main(string[] args)
            {
                //简单迭代器操作
                object[] values = { "我", "爱", "的", "是", "C#" };//初始化数组“我爱的是C#”
                Sample collection = new Sample(values, 3);         //Sample类实例化
                foreach (object x in collection)                    //循环打印
                {
                    Console.WriteLine(x);
                }
                Console.ReadKey();
            }
    

     以上是手写迭代器,还有一个更简便的方法,可以省去IterationSample类的迭代,即只需要Sample类GetEnumerator方法添加for循环语句,利用yield ruturn便可得到我们所希望的结果:

            // 摘要:返回一个循环访问集合的枚举器。
            // 返回结果:可用于循环访问集合的 System.Collections.IEnumerator 对象。
            public IEnumerator GetEnumerator()      
            {
                //return new IterationSample(this);
                //此方法减少代码量,是代码更优雅
                for (int index = 0; index < this.values.Length; index++)
                {
                    yield return values[(index + starting) % values.Length];
                }
            }
    

    IEnumerable<T>在LINQ中最重要的一个接口,如果想要在LINQ To Object上实现自己的LINQ操作,就会觉得迭代的方便性。值得注意的是,yield return语句停止了方法的执行,而不是退出方法,要想退出需要yield break,这根普通方法中的return一样。 

  • 相关阅读:
    嵌入式C语言编程小技巧
    冒号:在linux bash中的各种用法
    巧用ls命令
    嵌入式C精华提炼1
    不知道这些,别说你是嵌入式工程师!
    这些ARM基础知识你还不知道吗
    代码示例_C_冒泡
    代码示例_文件IO_lseek
    代码示例_文件IO_read / write
    代码示例_标准IO_fseek
  • 原文地址:https://www.cnblogs.com/baiboy/p/diedaiqi.html
Copyright © 2011-2022 走看看