C#中的yield return

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

来看看专业的解释:

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

看如下例子:

       public class CustomCollection :IEnumerable {

           public static void Main (string[] args)
{
CustomCollection cc = new CustomCollection (); foreach (String word in cc) {
Console.WriteLine ("word:" +word);
}
} public IEnumerator GetEnumerator(){ yield return "Hello";
yield return "Boys";
yield return "And";
yield return "Girls";
//return new HelloBoyGirls(); }
} // public class HelloBoyGirls: IEnumerator {
// private int cusor = -1;
// private String[] words = {"Hello", "Boys", "And", "Girls"};
//
// public bool MoveNext ()
// {
// cusor++;
// return cusor < words.Length;
// }
//
// public void Reset ()
// {
// cusor = 0;
// }
//
// public object Current {
// get {
// return words [cusor];
// }
// }
// }

上面的例子是实现了一个自定义的迭代器;实现可迭代(可以用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 循环自己控制:

     public class CustomCollection :IEnumerable {

         public static void Main (string[] args)
{
CustomCollection cc = new CustomCollection (); IEnumerator enumerator = cc.GetEnumerator ();
while (true) {
bool canMoveNext = enumerator.MoveNext ();
Console.WriteLine ("canMoveNext:" +canMoveNext);
if (!canMoveNext)
break;
Object obj = enumerator.Current;
Console.WriteLine ("current obj:" +obj);
}
// foreach (String word in cc) {
// Console.WriteLine ("word:" +word);
// }
Console.WriteLine ("Main End."); } public IEnumerator GetEnumerator(){ yield return "Hello";
yield return "Boys";
yield return "And";
yield return "Girls"; Console.WriteLine ("After all yield returns.");
//return new HelloBoyGirls(); }
}

运行代码, 结果是:

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 之后的语句, 不会被执行!

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

C#中的yield return与Unity中的Coroutine(协程)(上)的更多相关文章

  1. C#中的yield return与Unity中的Coroutine(协程)(下)

    Unity中的Coroutine(协程) 估计熟悉Unity的人看过或者用过StartCoroutine() 假设我们在场景中有一个UGUI组件, Image: 将以下代码绑定到Image using ...

  2. 可惜Java中没有yield return

    项目中一个消息推送需求,推送的用户数几百万,用户清单很简单就是一个txt文件,是由hadoop计算出来的.格式大概如下: uid caller 123456 12345678901 789101 12 ...

  3. C#中的yield return用法演示源码

    下边代码段是关于C#中的yield return用法演示的代码. using System;using System.Collections;using System.Collections.Gene ...

  4. Unity之"诡异"的协程

    为什么说是诡异的协程呢?首先从一个案例说起吧,示例如下: 游戏目标:让小车进入到对应颜色屋子里,即可获得一分.(转弯的道路可控)   为了让小车能够平滑转弯,小车的前进方向需要和车子的位置与圆心组成的 ...

  5. C#中的yield return

    4.1 迭代器块 一个迭代器块(iterator block)是一个能够产生有序的值序列的块.迭代器块和普通语句块的区别就是其中出现的一个或多个yield语句. yield return语句产生迭代的 ...

  6. Android中的Coroutine协程原理详解

    前言 协程是一个并发方案.也是一种思想. 传统意义上的协程是单线程的,面对io密集型任务他的内存消耗更少,进而效率高.但是面对计算密集型的任务不如多线程并行运算效率高. 不同的语言对于协程都有不同的实 ...

  7. Unity脚本编程之——协程(Coroutine)

    本文翻译自Unity官方文档:https://docs.unity3d.com/Manual/Coroutines.html 专有名词: Coroutine 协程 Alpha 不透明度 当你调用一个函 ...

  8. 【Unity笔记】使用协程(Coroutine)异步加载场景

    using UnityEngine; using System.Collections; using UnityEngine.SceneManagement; using System; public ...

  9. Unity带参数的协程

    两种方法都可以传递参数,代码如下: using UnityEngine; using System.Collections; public class Test : MonoBehaviour { v ...

随机推荐

  1. inux下文件权限设置中的数字表示权限,比如777,677等,这个根据什么得来的

    chmod ABC file 其中A.B.C各为一个数字,分别表示User.Group.及Other的权限. A.B.C这三个数字如果各自转换成由“0”.“1”组成的二进制数,则二进制数的每一位分别代 ...

  2. python datetime模块用strftime 格式化时间

    1 2 3 #!usr/bin/python import datetime datetime.datetime.now() 这个会返回 microsecond.因此这个是我们不需要的.所以得做一下修 ...

  3. 使用nmon监控服务器性能

    1.下载nmon:http://nmon.sourceforge.net/pmwiki.php?n=Site.Download 2.选择适合Linux系统版本的相应nmon版本,Linux查看系统版本 ...

  4. 【Android Demo】获取指定网页的页面源代码

    1.直接上效果图 2.代码 主要就是工具类HtmlService.java: import java.io.ByteArrayOutputStream; import java.io.InputStr ...

  5. 2014 Super Training #6 G Trim the Nails --状态压缩+BFS

    原题: ZOJ 3675 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3675 由m<=20可知,可用一个二进制数表 ...

  6. POJ 3255 Roadblocks --次短路径

    由于次短路一定存在,则可知次短路一定是最短路中某一条边不走,然后回到最短路,而且只是一条边,两条边以上不走的话,就一定不会是次短路了(即以边换边才能使最小).所以可以枚举每一条边,算出从起点到这条边起 ...

  7. HDU 1556 Color the ball

    这题用线段树的话简直就是一个水题..不过刚学树状数组,要用一下. 题意:每次给你a,b,表明a~b之间涂色,然后最后一次输出每个气球被涂色的次数. 要用树状数组就要考虑怎么转化为前缀和问题,这题可以这 ...

  8. CSU 1116 Kingdoms

    题意:给你n个城市,m条被摧毁的道路,每条道路修复需要c元,总共有k元,给你每个城市的人口,问在总费用不超过k的情况下 与1号城市相连的城市的最大总人口(包括1号城市) 思路:1号城市是必取的,剩余最 ...

  9. 第2章 面向对象的设计原则(SOLID):2_里氏替换原则(LSP)

    2. 里氏替换原则(Liskov Substitution Principle,LSP) 2.1 定义 (1)所有使用基类的地方必须能透明地使用子类替换,而程序的行为没有任何变化(不会产生运行结果错误 ...

  10. 转 异常处理汇总 ~ 修正果带着你的Net飞奔吧!

    异常处理汇总 ~ 修正果带着你的Net飞奔吧!   异常处理汇总-服 务 器 http://www.cnblogs.com/dunitian/p/4522983.html 异常处理汇总-开发工具  h ...