多角度让你彻底明白yield语法糖的用法和原理及在C#函数式编程中的作用
如果大家读过dapper源码,你会发现这内部有很多方法都用到了yield关键词,那yield到底是用来干嘛的,能不能拿掉,拿掉与不拿掉有多大的差别,首先上一段dapper中精简后的Query方法,先让大家眼见为实。
private static IEnumerable<T> QueryImpl<T>(this IDbConnection cnn, CommandDefinition command, Type effectiveType)
{
object param = command.Parameters;
var identity = new Identity(command.CommandText, command.CommandType, cnn, effectiveType, param?.GetType());
var info = GetCacheInfo(identity, param, command.AddToCache);
IDbCommand cmd = null;
IDataReader reader = null;
bool wasClosed = cnn.State == ConnectionState.Closed;
try
{
while (reader.Read())
{
object val = func(reader);
if (val == null || val is T)
{
yield return (T)val;
}
else
{
yield return (T)Convert.ChangeType(val, convertToType, CultureInfo.InvariantCulture);
}
}
}
}
一:yield探究
1. 骨架代码猜想
骨架代码其实很简单,方法的返回值是IEnumerable,然后return被yield开了光,让人困惑的地方就是既然方法的返回值是IEnumerable却在方法体内没有看到任何实现这个接口的子类,所以第一感觉就是这个yield不简单,既然代码可以跑,那底层肯定帮你实现了一个继承IEnumerable接口的子类,你说对吧?
2. msdn解释
有自己的猜想还不行,还得相信权威,看msdn的解释:https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/yield
如果你在语句中使用 yield 上下文关键字,则意味着它在其中出现的方法、运算符或 get 访问器是迭代器。 通过使用 yield 定义迭代器,可在实现自定义集合类型的 IEnumerator 和 IEnumerable 模式时无需其他显式类(保留枚举状态的类,有关示例,请参阅 IEnumerator)。
没用过yield之前,看这句话肯定是一头雾水,只有在业务开发中踩过坑,才能体会到yield所带来的快感。
3. 从IL入手
为了方便探究原理,我来写一个不能再简单的例子。
public static void Main(string[] args)
{
var list = GetList(new int[] { 1, 2, 3, 4, 5 });
}
public static IEnumerable<int> GetList(int[] nums)
{
foreach (var num in nums)
{
yield return num;
}
}
对,就是这么简单,接下来用ILSpy反编译打开这其中的神秘面纱。

从截图中看最让人好奇的有两点。
<1> 无缘无故的多了一个叫做<GetList>d__1 类
好奇心驱使着我看一下这个类到底都有些什么?由于IL代码太多,我做一下精简,从下面的IL代码中可以发现,果然是实现了IEnumerable接口,如果你了解设计模式中的迭代器模式,那这里的MoveNext,Current是不是非常熟悉?
多角度让你彻底明白yield语法糖的用法和原理及在C#函数式编程中的作用的更多相关文章
- 悉数 Python 函数传参的语法糖
TIOBE排行榜是程序开发语言的流行使用程度的有效指标,对世界范围内开发语言的走势具有重要参考意义.随着数据挖掘.机器学习和人工智能相关概念的风行,Python一举收获2018年年度语言,这也是Pyt ...
- Java语法糖(一)
概述 语法糖(Syntactic Sugar):主要作用是提高编码效率,减少编码出错的机会. 解语法糖发生在Java源码被编译成Class字节码的过程中,还原回简单的基础语法结构. 语法糖之一:泛型( ...
- day03 函数基本语法及特性 2. 参数与局部变量 3. 返回值 嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8.内置函数
本节内容 1. 函数基本语法及特性 2. 参数与局部变量 3. 返回值 嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8.内置函数 温故知新 1. 集合 主要作用: 去重 关系测 ...
- C# 基础小知识之yield 关键字 语法糖
原文地址:http://www.cnblogs.com/santian/p/4389675.html 对于yield关键字我们首先看一下msdn的解释: 如果你在语句中使用 yield 关键字,则意味 ...
- [lua]尝试一种Case语法糖
function CaseT(arg) function proxy(caller) caller.yield(r) end -- proxy return function (cond) if (c ...
- 刨根问底:if 后怎么就可以跟对象,变量交换写法是语法糖吗?
1.万物皆可布尔 一般语言中的 if 语句语法是这样的: if (条件表达式){ 执行语句} 而在 Python 中,if 后面不仅可以是条件表达式,还可以是任意对象.例如: my_list = ...
- 第十三节:实际开发中使用最多的监视锁Monitor、lock语法糖的扩展、混合锁的使用(ManualResetEvent、SemaphoreSlim、ReaderWriterLockSlim)
一. 监视锁(Monitor和lock) 1. Monitor类,限定线程个数的一把锁,两个核心方法: Enter:锁住某个资源. Exit:退出某一个资源. 测试案例:开启5个线程同时对一个变量进行 ...
- 【转】剖析异步编程语法糖: async和await
一.难以被接受的async 自从C#5.0,语法糖大家庭又加入了两位新成员: async和await. 然而从我知道这两个家伙之后的很长一段时间,我甚至都没搞明白应该怎么使用它们,这种全新的异步编程模 ...
- Python 语法糖装饰器的应用
Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现了say_hello()和say_goodbye()两个函数. def sa ...
随机推荐
- Git&sourceTree软件安装、使用说明及遇到问题解决
一.软件版本 1.Git版本为1.9.5 2.Source版本为1.5.2 二.软件安装步骤 1.Git安装步骤 1)双击Git安装文件进入下图界面,单击Next 2)继续Next 3)进入Selec ...
- Journal of Proteome Research | Improving Silkworm Genome Annotation Using a Proteogenomics Approach (分享人:张霞)
题目:Improving Silkworm Genome Annotation Using a Proteogenomics Approach 期刊:Journal of Proteome Resea ...
- nmap端口扫描工具安装和使用方法
nmap(Network Mapper)是一款开源免费的针对大型网络的端口扫描工具,nmap可以检测目标主机是否在线.主机端口开放情况.检测主机运行的服务类型及版本信息.检测操作系统与设备类型等信息. ...
- 【HDU5934】Bomb——有向图强连通分量+重建图
题目大意 二维平面上有 n 个爆炸桶,i−thi-thi−th爆炸桶位置为 (xi,yi)(x_i, y_i)(xi,yi) 爆炸范围为 rir_iri ,且需要 cic_ici 的价格引爆, ...
- [最短路,floyd] Codeforces 1204C Anna, Svyatoslav and Maps
题目:http://codeforces.com/contest/1204/problem/C C. Anna, Svyatoslav and Maps time limit per test 2 s ...
- 高效code review指南
大多数程序员都知道并且相信code review(代码审查)的重要性,但并一定都能很好的执行这一过程,做好code review也需要遵循一定的原则.流程和规范. 我们团队的code review实践 ...
- 我们是怎么实现gRPC CodeFirst-生成proto
前言: gRPC默认是ProtoFirst的,即先写 proto文件,再生成代码,需要人工维护proto,生成的代码也不友好,所以出现了gRPC CodeFirst,下面来说说我们是怎么实现gRPC ...
- Android初级控件
Android初级控件 从今天开始就对Android进行正式的学习,首先先来学习一下初级的控件 1.TextView 文本框,用于显示文字,不可编辑. 常用属性 android:autoLink ...
- PHP7内核(五):系统分析生命周期
上篇文章讲述了模块初始化阶段之前的准备工作,本篇我来详细介绍PHP生命周期的五个阶段. 一.模块初始化阶段 我们先来看一下该阶段的每个函数的作用. 1.1.sapi_initialize_reques ...
- Vue2.0 -- 钩子函数/ 过度属性/常用指令/以及Vue-resoure发送请求
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...