c# yield关键字原理
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接口实现的迭代功能。
转载于:https://www.cnblogs.com/kelelipeng/p/10042875.html
c# yield关键字原理相关推荐
- python生成器yield原理_生成器yield关键字详解
鉴于yield关键字的原理大家理解的都不是很深刻,今天我们主要就这一课题进行探讨. 生成器可以用什么方式得到? 方法一: 利用推导式的方式得到生成器# 列表推导式 list1 = [i for i i ...
- python function if yield_Python中的yield关键字
Python中的yield关键字 这是stackoverflow上一个关于yield关键字的问题以及它被推荐次数最高的一个答案 问题: Python中的yield关键字是什么?它是用来做什么的? 例如 ...
- Python 生成器 和 yield 关键字
Python 中 yield 的作用:http://youchen.me/2017/02/10/Python-What-does-yield-do/# Python 生成器详解:http://codi ...
- 反编译使用yield关键字的方法
我认为这是一个真命题:"没有用.NET Reflector反编译并阅读过代码的程序员不是专业的.NET程序员"..NET Reflector强大的地方就在于可以把IL代码反编译成可 ...
- python网络爬虫之yield关键字的使用!
yield关键字,33关键字之一! yield<- ->生成器 源源不断生成数据的生成器! 实例: 我的尝试: 为何用生成器: 优点如下: 更加节省存储空间 响应更加迅速 使用更加灵活 对 ...
- C#中使用的yield关键字是什么?
在" 如何仅显示IList <>的片段"问题中,答案之一具有以下代码片段: IEnumerable<object> FilteredList() {fore ...
- “ yield”关键字有什么作用?
Python中yield关键字的用途是什么? 它有什么作用? 例如,我试图理解这段代码1 : def _get_child_candidates(self, distance, min_dist, m ...
- 从range和xrange的性能对比到yield关键字(中)
2019独角兽企业重金招聘Python工程师标准>>> 上节提出了range和xrange的效率问题,这节我们来探究其中的原因 yield的使用 我们看下面的程序: #coding: ...
- Python的yield关键字
http://blog.csdn.net/tossgoer/archive/2010/08/18/5822303.aspx 忽然得知Python有个叫yield的关键字,好奇之下去查了查,花了点时间基 ...
最新文章
- 致广大关注《网络规划设计师考试案例梳理、真题透解与强化训练》读者朋友的一封信...
- yum源简单介绍及本地yum源的搭建
- MySQL存储结构的使用
- 2021HDU多校6 - 7028 Decomposition(构造)
- Oracle优化检查表
- html展示pdf文件流,使用pdfjs提供的viewer.html展示pdf文件流
- 数据结构之顺序栈的一些基本操作
- 求出2个字符串中的最大公共子串
- 蓝桥杯 ADV-20 算法提高 交换Easy
- 蓝桥杯2014c++真题:切面条
- wcf中如何Host多个WCF服务?
- Unity之UGUI初探—按钮动画
- 安装 Linux 系统,如何选择操作系统和电脑硬件
- Cisco ASA 5585防火墙ASDM配置
- qq旋风离线服务器维护,如何进入qq旋风离线空间
- 51单片机控制42步进电机——程序实现(中断PWM/延时函数)
- [硬件]_ELVE_STLINK下载出现nternal command error问题
- nodejs调用SendCloud邮件API2.0
- vos3000外呼系统讯时O口网关加密注册 VOS 配置方法
- oracle完整的练习,2021史上最全Oracle数据库基本操作练习题(含答案).docx