多角度让你彻底明白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 ...
随机推荐
- Spring解决循环依赖,你真的懂了吗?
导读 前几天发表的文章SpringBoot多数据源动态切换和SpringBoot整合多数据源的巨坑中,提到了一个坑就是动态数据源添加@Primary接口就会造成循环依赖异常,如下图: 这个就是典型的构 ...
- Fiddler5 发送HTTP请求
1.Fiddler Composer发送HTTP请求 Composer的编辑模式主要有2种:Parsed模式和Raw模式. 实例1:Composer发送get请求 实例2:Composer发送post ...
- ElegantSnap 一个优雅的,易用的iOS/tvOS/macOS自动布局框架, 超级详细的使用教程,多视图水平等宽/垂直等高排列
ElegantSnap ElegantSnap(Base on SnapKit) to make Auto Layout easy and elegant on both iOS and OS X. ...
- 安装自动化测试工具webdriver与selenium模块
webdriver是一个驱动,需要与selenium配合使用,selenium是自动化测试和爬虫的专业模块,对于不同的浏览器需要不同的webdriver,这里我用的是ubuntu19.10的系统,以p ...
- varchar int 查询 到底什么情况下走索引?
一个字符类型的.一个int类型的,查询的时候到底会不会走索引,其实很多工作了几年的开发人员有时也会晕,下面就用具体事例来测试一下. 1. 准备工作 先准备2张表,以备后续测试使用. 表1:创建表te ...
- 知识图谱与机器学习 | KG入门 -- Part1 Data Fabric
介绍 如果你在网上搜索机器学习,你会找到大约20500万个结果.确实是这样,但是要找到适合每个用例的描述或定义并不容易,然而会有一些非常棒的描述或定义.在这里,我将提出机器学习的另一种定义,重点介绍一 ...
- 使用charAt()方法查找字符串
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8 ...
- nodejs使用express中静态资源托管(express.static())时遇到的bug
如下:将test.html的页面挂载在服务器上, const express= require('express') const fs= require('fs') let app = express ...
- CUDA编程入门
CUDA是一个并行计算框架.用于计算加速.是nvidia家的产品.广泛地应用于现在的深度学习加速. 一句话描述就是:cuda帮助我们把运算从cpu放到gpu上做,gpu多线程同时处理运算,达到加速效果 ...
- office2010安装与破解,笔者亲测可用!!!!!!
我们首先需要准备office2010安装包与破相应的破解软件.软件包的获取方式:扫码关注[猿成长],,回复 office2010安装,即可获取,下载解压后文件目录结构如下图所示: 打开安装程序文件夹, ...