多角度让你彻底明白yield语法糖的用法和原理及在C#函数式编程中的作用

Posted dotNET跨平台

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多角度让你彻底明白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 style="box-sizing: border-box;"> 无缘无故的多了一个叫做\ d__1 类

好奇心驱使着我看一下这个类到底都有些什么?由于IL代码太多,我做一下精简,从下面的IL代码中可以发现,果然是实现了IEnumerable接口,如果你了解设计模式中的迭代器模式,那这里的MoveNext,Current是不是非常熟悉?

以上是关于多角度让你彻底明白yield语法糖的用法和原理及在C#函数式编程中的作用的主要内容,如果未能解决你的问题,请参考以下文章

深入LUA脚本语言,让你彻底明白调试原理

8000字长文让你彻底了解 Java 8 的 Lambda函数式接口Stream 用法和原理

不了解这12个语法糖,别说你会Java!

原创 | 不了解这12个语法糖,别说你会Java!

什么是语法糖?Java中有哪些语法糖?

从jvm角度来解析java语法糖