C# yeild的使用使用教程与实战指南实用指南
平时做技术实践时,很多问题不是概念不会,而是细节没串起来。拿“C# yeild的采用”来说,它看着像小点,放到项目里常会牵出环境、配置、兼容性和维护成本。下面按实际采用顺序,把思路、关键写法和容易踩坑的地方讲清楚,便于大家直接对照操作。
落到代码里,yield 是 C# 中一个很巧妙的语法糖,它的核心作用是实现“延迟执行(Lazy Evaluation)”。
实际处理时,轻松来说,它允许你在一个方法中逐个得到数据,而不需一次性把所有数据都计算好并塞进一个 List 里得到。
核心概念:从“批发”到“零售”
为便于理解 yield,我们先看一个不采用 yield 的传统写法:
// 传统写法:一次性生成所有数据(批发)
public List<int> GetNumbers(int count)
{
var list = new List<int>();
for (int i = 0; i < count; i++)
{
list.Add(i); // 把所有数字都塞进内存里的集合
}
return list; // 最后一次性返回整个集合
}
缺点:如果 count 是 100 万,这个方法会瞬间在内存中分配一个包含 100 万个元素的数组,造成极大的内存浪费。
现在看看采用 yield 的写法:
// yield 写法:按需生成数据(零售)
public IEnumerable<int> GetNumbersYield(int count)
{
for (int i = 0; i < count; i++)
{
yield return i; // 每次吐出一个数字,然后“暂停”在这里
}
}
优点:调用这个方法时,它根本不会立刻执行循环。只有当外部真正去读取下一个数据时,它才会执行一次循环,吐出一个值,随后暂停。内存中永远只存在当前这一个数字。
两个核心关键字
- 从实现思路看,yield return:得到当前值,同时记住当前的执行状态(包括局部变量、循环索引等)。下次调用时,直接从这行代码的下一行继续执行。
- yield break:提前结束迭代,相当于普通方法里的 return。
典型应用场景
1. 读取超大文件或数据流
结合项目来看,假设你要读取一个 10GB 的日志文件,如果用 File.ReadAllLines(),内存直接撑爆。用 yield 能够逐行处理:
public IEnumerable<string> ReadLargeFile(string filePath)
{
using (var reader = new StreamReader(filePath))
{
string line;
while ((line = reader.ReadLine()) != null)
{
yield return line; // 读一行,吐出一行,内存占用极小
}
}
}
// 使用时:
foreach (var line in ReadLargeFile("huge_log.txt"))
{
if (line.Contains("ERROR")) Console.WriteLine(line);
}
2. 实现自定义迭代器
实际处理时,若你想让你自己写的类兼容 foreach 循环,就能够用 yield:
public class Countdown
{
private int _start;
public Countdown(int start) { _start = start; }
public IEnumerator<int> GetEnumerator()
{
for (int i = _start; i >= 0; i--)
{
yield return i;
}
}
}
// 使用时:
var countdown = new Countdown(5);
foreach (var num in countdown)
{
Console.WriteLine(num); // 输出 5, 4, 3, 2, 1, 0
}
3. 提前终止(yield break)
public IEnumerable<int> GetEvenNumbers(int max)
{
for (int i = 0; i <= max; i++)
{
if (i > 10) yield break; // 如果超过10,直接结束整个迭代
if (i % 2 == 0) yield return i;
}
}
必须注意的“坑”
- 只能得到特定类型:包含 yield 的方法,得到类型只能是 IEnumerable、IEnumerable
、IEnumerator 或 IEnumerator 。不能直接得到 List 或数组。 - 延迟执行的副作用:
var query = GetNumbersYield(100); // 此时循环一次都没执行!
如果你在 GetNumbersYield 里面有参数校验(比如 if(count < 0) throw...),在调用方法时不会报错,只有在 foreach 第一次迭代时才会报错。
// 只有走到这里,循环才开始
foreach(var item in query) { ... } - 理解这一步时,不要在 yield 方法里采用 try-catch-finally 包裹 yield return:C# 编译器不允许在包含 yield return 的 try 块中采用 catch(但能够采用 finally)。
总结
从实现思路看,yield 的本质是状态机。C# 编译器在底层帮你把 yield 方法编译成了一个复杂的类,自动帮你保存了局部变量和执行位置。
一句话口诀:当数据量很大,或者数据是按需生成的,且你只需用 foreach 去遍历它时,果断采用 yield return。
在这个场景下,总的来说,C# yeild适合结合实际项目边做边理解。先抓住核心思路,再逐步补上细节和边界处理,最后效果会更稳定,也更容易复用。
-
10.11
C# yeild的使用使用教程与实战指南实用指南
-
10.11
C#常用类库Grpc.Core.Api的使用小结实用指南
-
10.11
Codex提效技巧整理分享:7个适合新手直接照抄的提示词模板实用指南
-
10.11
OpenClaw阿里云部署实践指南:从服务器搭建到QQ端接入使用实用指南
-
10.11
DeepSeek Harness第三方模型配置实践教程:桌面端、网页端与兼容接口实测实用指南
-
10.11
DeepSeek Harness配置模型失败排查:MISSING_CREDENTIAL、UNKNOWN_MODEL及请求被拒的完整解法实实用指南
-
-
下载
- |
-
-
下载
- 《行尸走肉第一章》免安装中文汉化硬盘版下载
- 单机|436 MB
- 一款以动作冒险为主题的游戏
-
-
下载
- 《街头霸王X铁拳》免安装中文汉化硬盘版下载
- 单机|111MB
- 一款非常好玩的格斗游戏
-
-
下载
- |
-
-
下载
- 《暗黑破坏神3》免安装繁体中文正式版下载
- 单机|7630 MB
- 一款以角色扮演为主题的游戏
-
-
下载
- 《马克思佩恩3》免安装硬盘版下载
- 单机|27033 MB
- 一款以第三人称射击为主题的游戏