关于c#:什么时候’屈服’真的需要?

When is 'Yield' really needed?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
C# - Proper Use of yield return

什么是C收益的真正用例?

谢谢。


当你想要延期执行的时候。

这在大多数情况下都是有意义的,在这种情况下,替代方法是构造一个临时集合。

考虑这个场景:我有一个整数列表,我想列出它们的平方。

我可以这样做:

1
2
3
4
5
6
7
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。我可以用yield枚举初始列表,并逐个返回方块:

1
2
3
4
public static IEnumerable<int> Squares(this IEnumerable<int> numbers) {
    foreach (int number in numbers)
        yield return number * number;
}

事实上,这确实起到了作用,直到您开始处理非常大的集合,在那里填充临时集合被证明是非常浪费的,这一点可能并不明显。

例如,假设我想找到高于某个阈值的第一个平方。我可以这样做:

1
2
3
4
5
IEnumerable<int> numbers = GetLotsOfNumbers();
var squares = numbers.Squares();
int firstBigSquare = squares
    .Where(x => x >= 1000)
    .FirstOrDefault();

但是,如果我的Squares方法在返回之前填充了整个List,那么上面的代码可能要做的工作比需要的要多得多。


yield上的msdn页面:

Used in an iterator block to provide a value to the enumerator object or to signal the end of iteration.

在创建自定义迭代器时使用它。使用页面中的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// yield-example.cs
using System;
using System.Collections;
public class List
{
    public static IEnumerable Power(int number, int exponent)
    {
        int counter = 0;
        int result = 1;
        while (counter++ < exponent)
        {
            result = result * number;
            yield return result;
        }
    }

    static void Main()
    {
        // Display powers of 2 up to the exponent 8:
        foreach (int i in Power(2, 8))
        {
            Console.Write("{0}", i);
        }
    }
}

yield表示Power中的while循环在每次迭代后有效地"暂停",以允许调用例程执行某些操作。在这种情况下,打印出结果。


当你懒得写自己的IEnumerator时;)


请参阅本文。

yield充当返回占位符——它是一个非本地的goto返回点,用于保留方法的环境并允许代码"跳转"回。以一种类似(有点倒转)的方式将委托传递到一个方法中,该方法允许您在另一个方法中注入特定的逻辑,闭包允许您围绕一个更通用的方法"执行"不同类型的工作,允许您保持代码的小型化、模块化和可重用性。

这可以使代码更加高效。不是实例化一个非常大的集合,而是可以允许对单个对象按顺序进行操作(并且在每次操作后都会丢弃这些对象)。我想您可以构造一个非常难以构建直接迭代器的情况。