yield return 是 C# 中实现延迟执行、节省内存的自定义迭代器的核心机制,支持按需生成序列、树遍历等场景,但受限于方法签名与语法约束。

在C#中,yield return 是实现自定义迭代器最简洁、高效的方式,它让方法能按需生成序列,无需一次性构造整个集合,节省内存且支持延迟执行。
yield return 的基本用法
被 yield return 修饰的方法必须返回 IEnumerable 或 IEnumerator,且不能有 return 语句(除 return; 外),也不能有 ref/out 参数或 try-catch 块(除非 catch 内无 yield,且 finally 中不能有 yield)。
每次调用迭代器的 MoveNext(),代码从上一次 yield return 暂停处继续执行,直到下一个 yield return 或方法结束。
- 每个
yield return返回一个元素,控制权交还给调用方 -
yield break可提前终止迭代,等效于自然退出 - 编译器会将含
yield的方法自动转换为状态机类(编译后可见)
实现简单数值序列的迭代器
例如生成 1 到 n 的平方数:
public static IEnumerableSquares(int n) { for (int i = 1; i <= n; i++) { yield return i * i; } }
调用时可直接用于 foreach 或 LINQ:
foreach (int sq in Squares(5))
Console.WriteLine(sq); // 输出 1, 4, 9, 16, 25注意:该方法不会立即执行循环,只有在第一次枚举时才开始计算——这就是延迟执行。
用 yield return 实现树的中序遍历
递归 + yield 是处理嵌套结构的常用模式。假设有一个二叉树节点类:
public class TreeNode
{
public int Value { get; set; }
public TreeNode Left { get; set; }
public TreeNode Right { get; set; }
}中序遍历(左-根-右)可这样写:
public static IEnumerableInOrder(TreeNode node) { if (node == null) yield break; foreach (var v in InOrder(node.Left)) yield return v; yield return node.Value; foreach (var v in InOrder(node.Right)) yield return v;}
这种方式逻辑清晰,避免手动维护栈,也保持了延迟求值特性——遍历到哪才计算到哪。
注意事项与常见误区
yield return 看似简单,但容易踩坑:
- 不能在匿名方法、lambda 表达式或异步方法(
async)中使用yield- 局部变量在多次迭代中会被保留(闭包行为),注意引用生命周期
- 每次调用迭代器方法都会创建新的枚举器,互不影响;但若方法内捕获了外部可变状态,需谨慎线程安全
- 调试时无法在
yield return行设断点(VS 中可能跳过),建议用日志或拆分逻辑辅助排查基本上就这些。掌握
yield return后,写数据流处理、配置解析、文件逐行读取等场景会变得非常自然和轻量。










