yield 关键字在 C# 中不是用来“返回值”或“跳出方法”的,而是专门用于声明迭代器方法(iterator method)——它让方法能逐个提供序列元素,同时自动帮你管理状态,不用手动写复杂的迭代器类。
让方法变成可迭代的序列生成器
普通方法只能一次性返回一个结果,而用 yield return 的方法,每次调用
MoveNext()(比如在
foreach中)时,会从上次暂停的位置继续执行,直到遇到下一个 yield return 或方法结束。这样你就能用很简洁的代码写出“边算边给”的逻辑。 方法返回类型必须是
IEnumerable<t></t>、
IEnumerator<t></t>或其非泛型对应类型 方法体内不能有
return value;(但可以有
return;表示结束迭代) 不能在匿名方法、lambda 表达式或 async 方法中使用 yield(C# 7.0+ 支持 async 迭代器,但需用
IAsyncEnumerable<t></t>和
yield return配合
await)
编译器自动生成状态机,你不用操心细节
你写的含 yield 的方法,编译器会在后台生成一个私有嵌套类(状态机),实现
IEnumerator<t></t>接口,并维护当前执行位置、局部变量等状态。你完全不用手动实现
Current、
MoveNext()、
Dispose()等成员。 所有局部变量会被“提升”为状态机类的字段,保证跨多次
MoveNext()调用时值不丢失 每个 yield return 对应一个状态编号,编译器用
switch控制流程跳转 调试时能看到自动生成的
<methodname>d__N</methodname>类,但日常开发无需关注
常见实用场景:延迟计算 + 节省内存
适合处理大数据流、无限序列、IO 边读边处理等场景,避免一次性加载全部数据到内存。
遍历文件行:foreach (var line in ReadLines("log.txt")) { ... },每行只读一次、不缓存全文
生成斐波那契数列:yield return a; int temp = a; a = b; b = temp + b;,按需计算下一项 过滤并转换集合:
foreach (var x in source) if (x > 0) yield return x * 2;,链式处理无中间数组
注意:yield break 提前终止迭代
yield break 不是退出方法,而是告诉迭代器“这里没更多元素了”,后续调用
MoveNext()将返回
false。常用于条件提前结束,比如空集合检查或达到阈值。
if (items == null) yield break;
for (int i = 0; i
基本上就这些。用好 yield,写迭代逻辑更轻量、更直观,也更符合 .NET 的惯用风格。
