zoukankan      html  css  js  c++  java
  • 实现迭代器的捷径

    迭代器模式是行为模式的一种范例,行为模式是一种简化对象之间通信的设计模式。它允许你访问一个数据序列中的所有元素,而无须关心序列是什么类型。它能有效的构建一个数据管道,经过一系列不同的转换或过滤后再从管道的另一端出来。(也是LINQ核心模式之一)

    迭代模式是通过IEnumerator和IEnumerable接口及它们的泛型等价物来封装的。
    foreach语句被编译后会调用GetEnumerator和MoveNext方法以及Current属性,如果实现IDisposable,程序还是自动销毁迭代对象。
    C#1:手写迭代器痛苦
    迭代模式不用一次返回所有数据——调用代码一次只需获取一个元素。
    #region 6-1使用新集合类型代码
    object[] values = { "a", "b", "c", "d", "e" };
    IterationSample collection = new IterationSample(values, 3);
    foreach (object x in collection)
    {
    Console.WriteLine(x);
    }
    #endregion
    #region 新集合类型框架,不包含迭代器的实现
    public class IterationSample : IEnumerable
    {
    public object[] values;
    public int startingPoint;
     
    public IterationSample(object[] values, int startingPoint)
    {
    this.values = values;
    this.startingPoint = startingPoint;
    }
     
    public IEnumerator GetEnumerator()
    {
    return new IterationSampleIterator(this);
    }
     
    }
    #endregion
    #region 6-3 嵌套类实现集合迭代器
    class IterationSampleIterator : IEnumerator
    {
    IterationSample parent;//正在迭代的集合
    int position;
     
    internal IterationSampleIterator(IterationSample parent)
    {
    this.parent = parent;
    position = -1;
    }
     
    public bool MoveNext()// 将枚举数推进到集合的下一个元素。
    {
    if (position != parent.values.Length)//遍历,增加position值
    {
    position++;
    }
    return position < parent.values.Length;
    }
     
    public object Current// 获取集合中的当前元素。先调用MoveNext方法
    {
    get
    {
    if (position == -1 || position == parent.values.Length)//防止访问第一个元素之前和最后一个元素之后
    {
    throw new InvalidOperationException();
    }
    int index = position + parent.startingPoint;
    index = index % parent.values.Length;//获取当前索引下标
    return parent.values[index];
    }
    }
     
    public void Reset()
    {
    position = -1;
    }
    }
    #endregion
    C#2:利用yield语句简化迭代器
    #region 6-4 利用C#2和yieid return来迭代实例
    public IEnumerator GetEnumerator()
    {
    for (int index = 0; index < values.Length; index++)
    {
    yield return values[(index + startingPoint) % values.Length];//实现迭代器的方法
    }
    }
    #endregion
    迭代器工作流程
    #region 6-5
    static readonly string Padding = new string(' ', 30);
    static IEnumerable<int> CreateEnumerable()
    {
    Console.WriteLine("{0}Start of CreateEnumerable()", Padding);
     
    for (int i = 0; i < 3; i++)
    {
    Console.WriteLine("{0}About to yield {1}", Padding, i);
    yield return i; //代码停止执行,下次调用MoveNext时继续调用
    Console.WriteLine("{0}After yield", Padding);
    }
    Console.WriteLine("{0}Yielding final value", Padding);
    yield return -1;
     
    Console.WriteLine("{0} End of CreateEnumerable()", Padding); //返回false结束方法执行
    }
    #endregion
    #region 6-5显示迭代器及其调用者之间的调用序列
    IEnumerable<int> iterable = CreateEnumerable();
    IEnumerator<int> iterator = iterable.GetEnumerator();
    Console.WriteLine("string to iterate");
    //while (true)
    //{
    // Console.WriteLine("Calling MoveNext()...");
    // bool result = iterator.MoveNext();
    // Console.WriteLine("...MoveNext result={0}", iterator.Current);
    //}
    for (int i = 0; i < 7; i++)
    {
    Console.WriteLine("Calling MoveNext()...");
    bool result = iterator.MoveNext();
    Console.WriteLine("...MoveNext result={0}", result);
    }
    #endregion
    return作用:
    一:给调用者提供返回值
    二:退出时执行合适的finally代码块
    使用yield break结束迭代器的执行,finally代码块的执行
    #region 6-6演示yield break语句
     
    DateTime stop = DateTime.Now.AddSeconds(1);//停止时间
    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();//测试时间
    foreach (int i in CountWithTimeLimit(stop))
    {
    Console.WriteLine("Received {0}", i);
     
    Thread.Sleep(10);//执行一次,间隔时间
    }
    stopwatch.Stop();
    double mm = stopwatch.ElapsedMilliseconds;
    Console.WriteLine(mm);
    #endregion
    #region 6-6
    static IEnumerable<int> CountWithTimeLimit(DateTime limit)
    {
    try
    {
    for (int i = 1; i <= 100; i++)
    {
    if (DateTime.Now >= limit)
    {
    yield break;//时间到了,停止运行
    }
    yield return i;//暂时停止方法,并没有退出方法
    }
    }
    finally
    {
    Console.WriteLine("Stooping");
    }
    }
    #endregion
    具体实现中的奇特之处
    第一次调用MoveNext之前,Current属性总是返回迭代器产生类型的默认值
    在MoveNext返回false之后,Current属性总是返回最后的生成值
  • 相关阅读:
    Hapoop 搭建 (五)搭建zookeeper集群环境
    Hapoop 搭建 (四)搭建后测试
    Hapoop 搭建 (二)设置虚拟机SSH无密钥登陆
    Hapoop 搭建 (一)设置虚拟机与主机同一个网段
    windows上vmware 虚拟机,局域网其他主机访问
    Hadoop HDFS命令行操作
    jenkins配置
    WebAPI 实现前后端分离的示例
    Merge join、Hash join、Nested loop join对比分析
    SQL Server nested loop join 效率试验
  • 原文地址:https://www.cnblogs.com/Tan-sir/p/5169211.html
Copyright © 2011-2022 走看看