• C#中的yield return与Unity中的Coroutine(协程)(上)


    C#中的yield return

    C#语法中有个特别的关键字yield, 它是干什么用的呢?

    来看看专业的解释:

    yield 是在迭代器块中用于向枚举数对象提供值或发出迭代结束信号。它的形式为下列之一:
    yield return <expression>;
    yield break

     

    看如下例子:

     

     1  1     public class CustomCollection :IEnumerable {
     2  2         
     3  3         public static void Main (string[] args)
     4  4         {
     5  5             CustomCollection cc = new CustomCollection ();
     6  6 
     7  7             foreach (String word in cc) {
     8  8                 Console.WriteLine ("word:" +word);
     9  9             }
    10 10         }
    11 11 
    12 12         public IEnumerator GetEnumerator(){
    13 13 
    14 14             yield return "Hello";
    15 15             yield return "Boys";
    16 16             yield return "And";
    17 17             yield return "Girls";
    18 18             //return new HelloBoyGirls();
    19 19 
    20 20         }
    21 21     }
    22 22 
    23 23 //    public class HelloBoyGirls: IEnumerator {
    24 24 //        private int cusor = -1;
    25 25 //        private String[] words = {"Hello", "Boys", "And", "Girls"};
    26 26 //        
    27 27 //        public bool MoveNext ()
    28 28 //        {
    29 29 //            cusor++;
    30 30 //            return cusor < words.Length;
    31 31 //        }
    32 32 //
    33 33 //        public void Reset ()
    34 34 //        {
    35 35 //            cusor = 0;
    36 36 //        }
    37 37 //
    38 38 //        public object Current {
    39 39 //            get {
    40 40 //                return words [cusor];
    41 41 //            }
    42 42 //        }
    43 43 //    }
    View Code

     

     

    上面的例子是实现了一个自定义的迭代器;实现可迭代(可以用foreach)的数据集合,必须实现GetEmumerator()方法,返回实现了IEmumerator的对象实例。

    完成这个, 有两种方法,一种是用上面注释掉的代码,一种是用yield return. yield return 需要配合IEmumerator进行使用, 在外部foreach循环中,它会执行GetEmumerator()方法,遇到yield return, 做了如下两件事情:

    1.记录下当前执行到的代码位置

    2. 将代码控制权返回到外部, yield return 后面的值, 作为迭代的当前值。

    当执行下一个循环, 从刚才记录的代码位置后面, 开始继续执行代码。

    简单地说, yield return 就是实现IEmumerator的超级简化版, 是不是很简单?

    那么问题又来了, yield return 是如何决定循环该结束,yield return 之后的代码, 什么时候执行呢?

    把上面的例子改造一下, 不要用方便的foreach了, 用while 循环自己控制:

     1     public class CustomCollection :IEnumerable {
     2         
     3         public static void Main (string[] args)
     4         {
     5             CustomCollection cc = new CustomCollection ();
     6 
     7             IEnumerator enumerator = cc.GetEnumerator ();
     8             while (true) {
     9                 bool canMoveNext = enumerator.MoveNext ();
    10                 Console.WriteLine ("canMoveNext:" +canMoveNext);
    11                 if (!canMoveNext)
    12                     break;
    13                 Object obj = enumerator.Current;
    14                 Console.WriteLine ("current obj:" +obj);
    15             }
    16 //            foreach (String word in cc) {
    17 //                Console.WriteLine ("word:" +word);
    18 //            }
    19             Console.WriteLine ("Main End.");
    20 
    21         }
    22 
    23         public IEnumerator GetEnumerator(){
    24 
    25             yield return "Hello";
    26             yield return "Boys";
    27             yield return "And";
    28             yield return "Girls";
    29 
    30             Console.WriteLine ("After all yield returns.");
    31             //return new HelloBoyGirls();
    32 
    33         }
    34     }
    View Code

    运行代码, 结果是:

    canMoveNext:True
    current obj:Hello
    canMoveNext:True
    current obj:Boys
    canMoveNext:True
    current obj:And
    canMoveNext:True
    current obj:Girls
    After all yield returns.
    canMoveNext:False
    Main End.

    说明, 在GetEmumerator()中, 只有yield return 语句, 外部调用MoveNext()都为true, current就是yield return后面的对象

    除了yield return, 还有yield break; yield break 的作用是, 停止循环, MoveNext()为false, yield break 之后的语句, 不会被执行!

    有兴趣的童鞋, 可以自己写个例子试试。

      

  • 相关阅读:
    POJ 3630 Phone List/POJ 1056 【字典树】
    HDU 1074 Doing Homework【状态压缩DP】
    POJ 1077 Eight【八数码问题】
    状态压缩 POJ 1185 炮兵阵地【状态压缩DP】
    POJ 1806 Manhattan 2025
    POJ 3667 Hotel【经典的线段树】
    状态压缩 POJ 3254 Corn Fields【dp 状态压缩】
    ZOJ 3468 Dice War【PD求概率】
    POJ 2479 Maximum sum【求两个不重叠的连续子串的最大和】
    POJ 3735 Training little cats【矩阵的快速求幂】
  • 原文地址:https://www.cnblogs.com/vivid-stanley/p/5272736.html
Copyright © 2020-2023  润新知