当您需要延迟执行时。
在大多数情况下,这是有意义的,而另一种选择是构建一个临时集合。
考虑以下场景:我有一个整数列表,想要列出它们的平方。
我可以这样做:
public static IEnumerable<int> Squares(this IEnumerable<int> numbers) {
List<int> squares = new List<int>();
foreach (int number in numbers)
squares.Add(number * number);
return squares;
}
然后我可以对它们的平方进行求和,求平均值,找到最大值等操作。
但我实际上不需要为此目的填充一个全新的List<int>
。我可以使用yield
枚举初始列表并逐个返回它们的平方:
public static IEnumerable<int> Squares(this IEnumerable<int> numbers) {
foreach (int number in numbers)
yield return number * number;
}
例如,假设我想找到某个阈值以上的第一个平方数。我可以这样做:
IEnumerable<int> numbers = GetLotsOfNumbers();
var squares = numbers.Squares();
int firstBigSquare = squares
.Where(x => x >= 1000)
.FirstOrDefault();
但是,如果我的Squares
方法在返回之前填充了整个List<int>
,那么上面的代码可能会做比必要更多的工作。
当你太懒了,不想自己写 IEnumerator 时 ;)
请参阅本文。
Yield作为返回占位符 - 它是一个非局部goto返回点,它保留了方法的环境,并允许代码“跳回”。 与将委托传递到方法中以允许您在另一个方法中注入特定逻辑(有点倒置)类似,闭包允许您在更通用的方法“周围”执行不同类型的工作,从而使您可以保持代码小型化,模块化和可重用性。
这可能会导致更高效的代码。 而不是实例化一个非常大的集合,可能可以允许按顺序对单个对象进行操作(并且在每个操作后将其丢弃)。 我想你可以构建一些情况,其中一个简单的迭代器将非常难以构建。