C#使用yield关键字提升迭代性能与效率
前言
yield关键字在C#中简化了数据迭代的方式,实现了按需生成数据,自动维护迭代状态,减少了内存占用,并允许在迭代时执行复杂逻辑。
传统迭代和yield迭代方式对比
咱们来看看传统迭代方式和yield关键字迭代方式对比,是否如传说中的代码实现起来更简洁和高效:
/// <summary>
/// 传统迭代方式和yield关键字迭代方式对比
/// </summary>
public static void IteratorComparisonRun()
{
Console.WriteLine("迭代器方法使用yield关键字:");
foreach (var number in GetNumbersWithYield())
{
Console.WriteLine(number);
}
Console.WriteLine("传统迭代方法返回一个List<int>");
var numbers = GetNumbersWithoutYield();
foreach (var number in numbers)
{
Console.WriteLine(number);
}
}
/// <summary>
/// 迭代器方法使用yield关键字
/// </summary>
/// <returns></returns>
public static IEnumerable<int> GetNumbersWithYield()
{
for (int i = 0; i < 6; i++)
{
yield return i;
}
}
/// <summary>
/// 传统迭代方法返回一个List<int>
/// </summary>
/// <returns></returns>
public static List<int> GetNumbersWithoutYield()
{
var numbers = new List<int>();
for (int i = 0; i < 6; i++)
{
numbers.Add(i);
}
return numbers;
}
输出结果:

yield延迟加载按需获取数据
yield关键字可以通过延迟执行的方式,仅在实际需要时生成数据,从而提高了性能和效率。
/// <summary>
/// yield关键字延迟加载按需获取数据
/// </summary>
public static void LazyLoadingRun()
{
Console.WriteLine("yield延迟加载按需获取数据 开始...");
foreach (var number in GetEvenNumbers(11))
{
Console.WriteLine($"返回值 === {number} ===");
Thread.Sleep(500);
}
Console.WriteLine("yield延迟加载按需获取数据 结束...");
}
/// <summary>
/// 使用yield返回偶数的迭代器方法
/// </summary>
/// <returns></returns>
public static IEnumerable<int> GetEvenNumbers(int number)
{
for (int i = 1; i < number; i++)
{
Console.WriteLine($"Yielding {i}");
if (i % 2 == 0)
{
yield return i; //只在需要时生成偶数
}
}
}
输出结果:

yield break显式示迭代结束
yield break:显式示迭代结束,如以下示例所示:
public static void YieldBreakRun()
{
Console.WriteLine(string.Join(" ", TakeWhilePositive(new int[] { 1, 3, 4, 5, -1, 3, 4 })));
//输出:1 3 4 5
Console.WriteLine(string.Join(" ", TakeWhilePositive(new int[] { 9, 8, 7, 6, 5, -5, 88, 100 })));
//输出:9 8 7 6 5
}
public static IEnumerable<int> TakeWhilePositive(IEnumerable<int> numbers)
{
foreach (int n in numbers)
{
if (n > 0)
{
yield return n;
}
else
{
yield break;
}
}
}
什么情况不能使用yield关键字
- 带有 in、ref 或 out 参数的方法。
- Lambda 表达式和匿名方法。
- 在 C# 13 之前,yield 在具有 unsafe 块的任何方法中都无效。从 C# 13 开始,可以在包含 unsafe 块的方法中使用 yield,但不能在 unsafe 块中使用。
- 不能在catch和finally块中使用yield return和yield break。
- 不能在具有catch块的try块中使用yield return和yield break。
- 可以在只有finally块的try块中使用yield return和yield break。
完整示例代码

参考文章
C#使用yield关键字提升迭代性能与效率的更多相关文章
- 使用C# yield关键字来提高性能和可读性
对于”yield”这个关键字我已经见过N次了,直到最近我才知道这个关键字所蕴含的力量.我将在下面展示出一些使用”yield”让你的代码有更高可读性和更好性能的例子. 为了让你对yield有一些快速概览 ...
- 使用yield关键字来提高性能
比如我们在开发当中往往会遇到这样的问题: public List<string> FindBobs(string [] names) { List<string> bobs ...
- 从range和xrange的性能对比到yield关键字(中)
上节提出了range和xrange的效率问题,这节我们来探究其中的原因 yield的使用 我们看下面的程序: #coding: utf-8 def test(): print 4 print ...
- Python:容器、迭代对象、迭代器、生成器及yield关键字
在了解Python的数据结构时,容器(container).可迭代对象(iterable).迭代器(iterator).生成器(generator).列表/集合/字典推导式(list, ...
- 从yield关键字看IEnumerable和Collection的区别
C#的yield关键字由来以久,如果我没有记错的话,应该是在C# 2.0中被引入的.相信大家此关键字的用法已经了然于胸,很多人也了解yield背后的“延迟赋值”机制.但是即使你知道这个机制,你也很容易 ...
- C#的yield关键字
using System; using System.Collections.Generic; using System.Reflection; using System.Text.RegularEx ...
- php yield关键字以及协程的实现
php的yield是在php5.5版本就出来了,而在初级php界却很少有人提起,我就说说个人对php yield的理解 Iterator接口 在php中,除了数组,对象可以被foreach遍历之外,还 ...
- (转) Python Generators(生成器)——yield关键字
http://blog.csdn.net/scelong/article/details/6969276 生成器是这样一个函数,它记住上一次返回时在函数体中的位置.对生成器函数的第二次(或第 n 次) ...
- 转载yield关键字理解
实现IEnumerable接口及理解yield关键字 [摘要]本文介绍实现IEnumerable接口及理解yield关键字,并讨论IEnumerable接口如何使得foreach语句可以使用. 本 ...
- HHVM 是如何提升 PHP 性能的?
背景 HHVM 是 Facebook 开发的高性能 PHP 虚拟机,宣称比官方的快9倍,我很好奇,于是抽空简单了解了一下,并整理出这篇文章,希望能回答清楚两方面的问题: HHVM 到底靠谱么?是否可以 ...
随机推荐
- (Python基础教程之十六)Python multidict示例–将单个键映射到字典中的多个值
1.什么是multidict词典> 在python中," multidict "一词用于指代字典,在字典中可以将单个键映射到多个值.例如 多重结构 multidictWith ...
- Java并发显式锁和显式条件队列
一 显式锁 在类中利用synchronized修饰的方法或者this代码块,均使用的是类的实例锁或者类的锁.这些锁都称为内置锁. 可以利用显式锁进行协调对象的访问.即ReentrantLock.这是一 ...
- think in java interview-高级开发人员面试宝典(二)
从现在开始,以样题的方式一一列出各种面试题以及点评,考虑到我在前文中说的,对于一些大型的外资型公司,你将会面临全程英语面试,因此我在文章中也会出现许多全英语样题. 这些题目来自于各个真实的公司,公司名 ...
- mac通过网线连接主机(fnOS)
一.mac端 mac是typec的,用了个转接头+网线直连主机,初始化的时候跟下面一致,默认都是自动的 点击详细信息,配置IPv4选择使用DHCP 二.主机端 主机端是最麻烦的,刚开始的时候怎么也找不 ...
- 获取n级父目录名称
DirectoryInfo GetPrant(DirectoryInfo path, int level) { DirectoryInfo temp = null; if (level > 1) ...
- 前端每日一知之你需要知道的JSON.stringify
脑图在线链接 本文内容依据[web开发]公众号精彩文章总结而来
- DDCA —— 片上网络互联
1. 路由 1.1 网络拓扑示例 Grid(网格) 网络拓扑通常是一个二维矩阵形式,每个节点(处理器)与其上下左右相邻的节点相连. 如果节点在边缘,某些方向上可能没有相邻节点(边界节点). Torus ...
- 各种各样的 Host Builder
各种各样的 Host Buider If you're building for the web or writing a distributed application, you might nee ...
- 加速人民币国际化,CIPS迎来三大变化
何谓CIPS? 人民币跨境支付系统(Cross-border Interbank Payment System,简称CIPS)是由中国人民银行组织开发的独立支付系统,为境内外金融机构人民币跨境和离岸业 ...
- PHP 简易的BASE64加密
有这样一个有趣的公式:x<100; (x*53*17)%100 = x;这个公司的原理:53*17=901,x*901,的数后2位数还是x:任何符合 a * b = 100 * n +1 的值 ...