C#迭代器的实现(二)观察迭代器的工作流程

  • 显示迭代器及其调用者之间的调用序列

 public static readonly string Padding = new string(' ', 30);
       public 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;
                Console.WriteLine("{0}After yield", Padding);
            }
            Console.WriteLine("{0}Yielding final value", Padding);
            yield return -1;
            Console.WriteLine("{0}End of CreateEnumerable() ", Padding);
        }
...
 IEnumerable<int> iterable = ItratorSequence.CreateEnumerable();
            IEnumerator<int> iterator = iterable.GetEnumerator();
            Console.WriteLine("Starting to iterate");

            while (true)
            {
                Console.WriteLine("Calling MoveNext()...");
                bool result = iterator.MoveNext();
                Console.WriteLine("... MoveNext result ={0}", result);
                if (!result)
                {
                    break;
                }
                Console.WriteLine("Fetching Current...");
                Console.WriteLine("... Current result={0}", iterator.Current);
            }
  1. 在第一次调用MoveNext之前,CreateEnumerable中的代码不会被调用
  2. 所有工作在调用MoveNext时就完成了,获取Current的值不会执行任何代码
  3. 在yield return的位置,代码就停止执行,在下一次调用MoveNext时又继续执行
  4. 在一个方法中的不同地方可以编写多个yield return语句
  5. 代码不会在最后的yield return处结束,而是通过返回false的MoveNext调用来结束方法的执行。
  • 使用yield break结束迭代器的执行

   public static IEnumerable<int> CountWithTimeLimit(DateTime limit)
        {
            for (int i = 0; i <= 100; i++)
            {
                if (DateTime.Now >= limit)
                {
                    yield break;//yield break会直接让for each 跳出
                }
                yield return i;
            }
        }

  DateTime stop = DateTime.Now.AddSeconds(2);

            IEnumerable<int> collection = ItratorSequence.CountWithTimeLimit(stop);
            foreach (int i in collection)
            {
                Console.WriteLine("Received {0}", i);
                Thread.Sleep(300);
            }
  1. yield break语句终止了迭代器的运行,让当前对MoveNext的调用返回false。
  • finally 代码块的执行

 public static IEnumerable<int> CountWithTimeLimit(DateTime limit)
        {
            try
            {
                for (int i = 0; i <= 100; i++)
                {
                    if (DateTime.Now >= limit)
                    {
                        yield break;
                    }
                    yield return i;
                }
            }
            finally
            {
                Console.WriteLine("Stopping!");//不管循环是否结束,这一行都回执行
            }
        }
  1. 当yield break被执行后,finally代码块里的代码就会被执行。
    DateTime stop = DateTime.Now.AddSeconds(2);
            IEnumerable<int> collection = ItratorSequence.CountWithTimeLimit(stop);

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

                if (i > 3)
                {
                    Console.WriteLine("Returning");
                    return;
                }
                Thread.Sleep(300);
            }


 public static IEnumerable<int> CountWithTimeLimit(DateTime limit)
        {
            try
            {
                for (int i = 0; i <= 100; i++)
                {
                    if (DateTime.Now >= limit)
                    {
                        yield break;
                    }
                    yield return i;
                }
            }
            finally
            {
                Console.WriteLine("Stopping!");
            }
        }
  1. 当调用的函数return后,finally代码块里的代码也会被执行到。
  2. 只要调用者使用了foreach循环,迭代器块中的finally将按照你期望的方式工作。
         DateTime stop = DateTime.Now.AddSeconds(2);
            IEnumerable<int> collection = ItratorSequence.CountWithTimeLimit(stop);
            IEnumerator<int> iterator = collection.GetEnumerator();
            iterator.MoveNext();
            iterator.Dispose();
  1. 其实是因为foreach会最终调用Dispose方法,
  2. 以上代码当手动调用Dispose方法时,finaly代码块里的部分也会被执行到。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值