https://www.cnblogs.com/blueberryzzz/p/8678700.html

c# yield关键字原理详解

1.yield实现的功能
yield return:
先看下面的代码,通过yield return实现了类似用foreach遍历数组的功能,说明yield return也是用来实现迭代器的功能的。

using static System.Console;
using System.Collections.Generic;class Program { //一个返回类型为IEnumerable<int>,其中包含三个yield return public static IEnumerable<int> enumerableFuc() { yield return 1; yield return 2; yield return 3; } static void Main(string[] args) { //通过foreach循环迭代此函数 foreach(int item in enumerableFuc()) { WriteLine(item); } ReadKey(); } } 输出结果: 1 2 3

yield break:
再看下面的代码,只输出了1,2,没有输出3,说明这个迭代器被yield break停掉了,所以yield break是用来终止迭代的。

using static System.Console;
using System.Collections.Generic;
class Program { //一个返回类型为IEnumerable<int>,其中包含三个yield return public static IEnumerable<int> enumerableFuc() { yield return 1; yield return 2; yield break; yield return 3; } static void Main(string[] args) { //通过foreach循环迭代此函数 foreach(int item in enumerableFuc()) { WriteLine(item); } ReadKey(); } } 输出结果: 1 2

2.只能使用在返回类型必须为 IEnumerable、IEnumerable<T>、IEnumerator 或 IEnumerator<T>的方法、运算符、get访问器中。

3.yield关键字的实现原理
我们用while循环代替foreach循环,发现我们虽然没有实现GetEnumerator(),也没有实现对应的IEnumerator的MoveNext(),和Current属性,但是我们仍然能正常使用这些函数。

class Program
{//一个返回类型为IEnumerable<int>,其中包含三个yield returnpublic static IEnumerable<int> enumerableFuc() { yield return 1; yield return 2; yield return 3; } static void Main(string[] args) { //用while循环代替foreach IEnumerator<int> enumerator = enumerableFuc().GetEnumerator(); while (enumerator.MoveNext()) { int current = enumerator.Current; WriteLine(current); } ReadKey(); } } 输出结果: 1 2 3

至于为什么会出现这种情况,我们可以用ILSpy对生成的exe进行反编译来找到原因。
由于直接反编译成C#会变为原样

所以我们选择反编译为带C#注释的IL代码,虽然可读性差点,但是可以详细的了解其中过的原理。
先来看Program翻译的情况,编译的时候自动生成了一个新的类。

接下来我们来仔细看这些代码,EnumerableFuc()返回了这个新的类。

看这个代码自动生成的类的实现,发现它继承了IEnumerable、IEnumerable<T>、IEnumerator 或 IEnumerator<T>,这时我们应该已经能猜到这个新的类就是我们没有实现对应的IEnumerator的MoveNext(),和Current属性,但是我们仍然能正常使用这些函数的原因了。

我们再来看一下这个类具体是如何实现迭代的呢,我们主要来看一下MoveNext()函数


每次调用MoveNext()函数都会将state加1,一共进行了4次迭代,前三次返回true,最后一次返回false,代表迭代结束。这四次迭代对应被3个yield return语句分成4部分的enumberableFuc()中的语句。

用enumberableFuc()来进行迭代的真实流程就是:
1.运行enumberableFuc()函数,获取代码自动生成的类的实例。
2.接着调用GetEnumberator()函数,将获取的类自己作为迭代器开始迭代。
3.每次运行MoveNext(),state增加1,通过switch语句可以让每次调用MoveNext()的时候执行不同部分的代码。
4。MoveNext()返回false,结束。
这也能说明yield关键字其实是一种语法糖,最终还是通过实现IEnumberable<T>、IEnumberable、IEnumberator<T>和IEnumberator接口实现的迭代功能。

标签: c#, .NET
« 上一篇:IEnumerator和IEnumerable详解

转载于:https://www.cnblogs.com/kelelipeng/p/10042875.html

c# yield关键字原理相关推荐

  1. python生成器yield原理_生成器yield关键字详解

    鉴于yield关键字的原理大家理解的都不是很深刻,今天我们主要就这一课题进行探讨. 生成器可以用什么方式得到? 方法一: 利用推导式的方式得到生成器# 列表推导式 list1 = [i for i i ...

  2. python function if yield_Python中的yield关键字

    Python中的yield关键字 这是stackoverflow上一个关于yield关键字的问题以及它被推荐次数最高的一个答案 问题: Python中的yield关键字是什么?它是用来做什么的? 例如 ...

  3. Python 生成器 和 yield 关键字

    Python 中 yield 的作用:http://youchen.me/2017/02/10/Python-What-does-yield-do/# Python 生成器详解:http://codi ...

  4. 反编译使用yield关键字的方法

    我认为这是一个真命题:"没有用.NET Reflector反编译并阅读过代码的程序员不是专业的.NET程序员"..NET Reflector强大的地方就在于可以把IL代码反编译成可 ...

  5. python网络爬虫之yield关键字的使用!

    yield关键字,33关键字之一! yield<- ->生成器 源源不断生成数据的生成器! 实例: 我的尝试: 为何用生成器: 优点如下: 更加节省存储空间 响应更加迅速 使用更加灵活 对 ...

  6. C#中使用的yield关键字是什么?

    在" 如何仅显示IList <>的片段"问题中,答案之一具有以下代码片段: IEnumerable<object> FilteredList() {fore ...

  7. “ yield”关键字有什么作用?

    Python中yield关键字的用途是什么? 它有什么作用? 例如,我试图理解这段代码1 : def _get_child_candidates(self, distance, min_dist, m ...

  8. 从range和xrange的性能对比到yield关键字(中)

    2019独角兽企业重金招聘Python工程师标准>>> 上节提出了range和xrange的效率问题,这节我们来探究其中的原因 yield的使用 我们看下面的程序: #coding: ...

  9. Python的yield关键字

    http://blog.csdn.net/tossgoer/archive/2010/08/18/5822303.aspx 忽然得知Python有个叫yield的关键字,好奇之下去查了查,花了点时间基 ...

最新文章

  1. 致广大关注《网络规划设计师考试案例梳理、真题透解与强化训练》读者朋友的一封信...
  2. yum源简单介绍及本地yum源的搭建
  3. MySQL存储结构的使用
  4. 2021HDU多校6 - 7028 Decomposition(构造)
  5. Oracle优化检查表
  6. html展示pdf文件流,使用pdfjs提供的viewer.html展示pdf文件流
  7. 数据结构之顺序栈的一些基本操作
  8. 求出2个字符串中的最大公共子串
  9. 蓝桥杯 ADV-20 算法提高 交换Easy
  10. 蓝桥杯2014c++真题:切面条
  11. wcf中如何Host多个WCF服务?
  12. Unity之UGUI初探—按钮动画
  13. 安装 Linux 系统,如何选择操作系统和电脑硬件
  14. Cisco ASA 5585防火墙ASDM配置
  15. qq旋风离线服务器维护,如何进入qq旋风离线空间
  16. 51单片机控制42步进电机——程序实现(中断PWM/延时函数)
  17. [硬件]_ELVE_STLINK下载出现nternal command error问题
  18. nodejs调用SendCloud邮件API2.0
  19. vos3000外呼系统讯时O口网关加密注册 VOS 配置方法
  20. oracle完整的练习,2021史上最全Oracle数据库基本操作练习题(含答案).docx

热门文章

  1. 项目构建之maven篇:2.HelloWorld项目构建过程
  2. solr安装-tomcat+solrCloud构建稳健solr集群
  3. 求大神给解释一下H3C ospf 双塔奇兵
  4. 使用Ext Form自动绑定Html中的Form元素
  5. 如何为ccflow工作流引擎增加一个优先级PRI?
  6. 紫色回归线:雅虎中国的运筹学
  7. 区块链将带来怎样的应用?
  8. 区块链和智能合约的关系
  9. 广度优先搜索(BFS)模板
  10. Parcelable与Serializable的比较