多角度让你彻底明白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 ...
随机推荐
- Angular介绍
Angulay介绍 1.介绍:是一个用于Html和TypeScript构建客户端应用平台与框架.Angular 本身就是用 TypeScript 写成的.基本构造块是 NgModule,它为组件提供了 ...
- 是时候了解Java Socket底层实现了
在Java中,提供了一系列Socket API,可以轻松建立两个主机之间的连接.读取数据,那底层到底怎么实现,很少人去关心.这其实最终还是通过调用操作系统提供得Socket接口完成(TCP/IP是由操 ...
- video.js 视频自动全屏播放
1.头部引用脚本 <link href="css/video-js.min.css" rel="stylesheet"> <link href ...
- VS2019 C++动态链接库的创建使用(4) - C语言客户端
前面提到过C++具有函数重载功能,所以引出的函数名会有变化,即名称改编,如果是C语言编写的客户端则无法正确识别. 处理方法: ①只需在宏定义中间增加 extern "C",但这种使 ...
- java触发full gc的几种情况概述
前言 近期被问及这个问题,在此记录整理一下. System.gc()方法的调用 此方法的调用是建议JVM进行Full GC,虽然只是建议而非一定,但很多情况下它会触发 Full GC,从而增加Full ...
- GitHub也会断供:美国制裁地区帐号都受限,毫无预警,个人页面直接404
请注意,GitHub也有断供危机. 如果你有GitHub私有库,是时候重新思考安全性,也是时候制定备份策略. 这不是杞人忧天,也不只温馨提示,而是已经发生的事实. 一位伊朗程序员,一觉醒来GitHub ...
- 构建一个简单的 Google Dialogflow 聊天机器人【上】
概述 本教程将向您展示如何构建一个简单的Dialogflow聊天机器人,引导您完成Dialogflow的最重要功能.您将学习如何: 创建Dialogflow帐户和第一个Dialogflow聊天机器人, ...
- 深度学习论文TOP10,2019一季度研究进展大盘点
9012年已经悄悄过去了1/3. 过去的100多天里,在深度学习领域,每天都有大量的新论文产生.所以深度学习研究在2019年开了怎样一个头呢? Open Data Science对第一季度的深度学习研 ...
- 记录一个不同的流媒体网站实现方法,和用Python爬虫爬它的坑
今天找到一片电影,想把它下载下来. 先开Networks工具分析一下: 初步分析发现,视频加载时会拉取TS格式的文件,推测这是一个m3u8的索引,记录着几百段TS文件,这样方便快进时加载. 但是实际分 ...
- h5 js数组Array方法总结
重新复习数组方法. 一.首先说一下构建一个数组. 1.直接定义一个数组. var a = [1,2,3]; 2.通过Array 对象new一个数组,但Array对象根据传参的不同会返回不同的数组对象. ...