• C#学习笔记迭代器


    foreach隐式调用无参的GetEnumerator 方法来获取一个enumerator,但是一个集合只能有一个无参的GetEnumerator 方法,通常有这样的需求,根据参数的不同实现不同的枚举顺序或者枚举方式.在这些情形下,可以利用iterator来实现返回enumerable interfaces的属性和方法.比如Stack<T>实现了IEnumerable<T>类型的TopToBottomBottomToTop
    using System.Collections.Generic;

    public class Stack<T>: IEnumerable<T>


    {

        T[] items;

        
    int
     count;

        
    public void Push(T data) {}


        
    public T Pop() {}

        
    public IEnumerator<T> GetEnumerator() {

            
    for (int i = count – 1; i >= 0--i) 
    {

               yield 
    return
     items[i];

            }


        }


        
    public IEnumerable<T> TopToBottom {

            
    get 
    {

               
    return this
    ;

            }


        }


        
    public IEnumerable<T> BottomToTop {

            
    get 
    {

                
    for (int i = 0; i < count; i++
    {

                        yield 
    return
     items[i];

                }


            }


        }


    }

    TopToBottom 属性简单的返回this,因为statck本身就是enumerable,BottomToTop 用iterator返回了一个enumerable ,下面的例子展示如何使用这些属性来枚举栈中的成员.
    using System;

    class Test

    {

        
    static void Main() {

            Stack
    <int> stack = new Stack<int>();

            
    for (int i = 0; i < 10; i++) stack.Push(i);

            
    foreach (int i in stack.TopToBottom) Console.Write("{0} ", i);

            Console.WriteLine();

            
    foreach (int i in stack.BottomToTop) Console.Write("{0} ", i);

            Console.WriteLine();

        }


    }


    当然这些属性也可以用在出foreach语句之外的地方,下面的例子展示了通过单独的Print 方法调用属性的结果.这个例子也展示了用iterator实现的含参的FromToBy 方法.
    using System;

    using System.Collections.Generic;

    class Test

    {

        
    static void Print(IEnumerable<int> collection) {

            
    foreach (int i in collection) Console.Write("{0} ", i);

            Console.WriteLine();

        }


        
    static IEnumerable<int> FromToBy(int from, int to, int by) {

            
    for (int i = from; i <= to; i += by) {

                yield 
    return i;

            }


        }


        
    static void Main() {

            Stack
    <int> stack = new Stack<int>();

            
    for (int i = 0; i < 10; i++) stack.Push(i);

            Print(stack.TopToBottom);

            Print(stack.BottomToTop);

            Print(FromToBy(
    10202));

        }


    }

    范型或者非范型的enumerable interfaces 接口都包含唯一的成员无参和返回类型为enumerable interface的GetEnumerator 方法,一个enumerable 做为一个enumerator 工厂(factory),欠当地实现enumerables 保证每次调用GetEnumerator 方法时产生独立的enumerators,如果enumerable 内部的状态在两次调用GetEnumerator没有改变,两次返回的enumerators 应该是顺序相同的同一个数据集.这个必须得到保证即使enumerators的声明周期交迭.
    using System;

    using System.Collections.Generic;

    class Test

    {

        
    static IEnumerable<int> FromTo(int from, int to) {

            
    while (from <= to) yield return from++;

        }


        
    static void Main() {

            IEnumerable
    <int> e = FromTo(110);

            
    foreach (int x in e) {

                
    foreach (int y in e) {

                    Console.Write(
    "{0,3} ", x * y);

                }


                Console.WriteLine();

            }


        }


    }

    上面的代码实现了简单的从1到10的乘法表,注意方法FromTo只被调用了一次来获取enumerable  e,但是e.GetEnumerator()方法调用了多次(通过foreach表达式)来产生多个相同的enumerators,这些enumerators 都封装了FromTo方法中指定的iterator代码,注意迭代器代码修改From的值.但是这些enumerators表现为各自独立,因为每个enumerator有自己的From和To参数的拷贝.enumerators 之间的短暂状态的共享是在实现enumerables 和enumerators的时候应该避免的比较容易违反的隐含缺陷,C# iterator被设计用来避免这些问题,从而用简单和直观的方式实现健壮的enumerables 和enumerators.
  • 相关阅读:
    1月27日 常用函数
    1月25日 JavaScript的DOM操作
    1月25日 JavaScript简介与语法
    1月24日 样式表案例
    5月14日 数字顺序打印并求和
    5月14日 根据班级人数,求平局分,最大值,最小值
    5月14日 九九乘法口诀
    5月14日 打印100以内与7有关的数
    5月14日 函数练习 100以内奇数的和
    5月14日 枚举类型
  • 原文地址:https://www.cnblogs.com/Farseer1215/p/285506.html
Copyright © 2020-2023  润新知