什么时候'屈服'真的需要?

时间:2010-06-07 14:11:19

标签: c# yield

  

可能重复:
  C# - Proper Use of yield return

C#yield的真实用例是什么?

感谢。

4 个答案:

答案 0 :(得分:25)

如果您需要deferred execution

在大多数情况下,这是有意义的,其中替代方案是构建临时集合。

考虑这种情况:我有一个整数列表,我想列出它们的正方形。

我可以这样做:

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>,那么上面的代码可能做更多的工作。

答案 1 :(得分:10)

来自MSDN page on yield

  

在迭代器块中使用,为枚举器对象提供值或表示迭代结束。

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

// 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表示while内的Power循环在每次迭代后有效“暂停”,以允许调用例程执行某些操作。在这种情况下打印出结果。

答案 2 :(得分:8)

当你懒得写自己的IEnumerator;)

答案 3 :(得分:1)

请参阅this article

Yield作为一个返回占位符 - 它是一个非本地goto返回点,它保留了方法的环境,并允许代码“跳回”。以类似的方式(反转)将委托传递给允许您在另一个方法中注入特定逻辑的方法,闭包允许您围绕一种更通用的方法执行不同类型的工作,允许您保持代码小,模块化和可重用。

这可以提高代码效率。可以允许单个对象按顺序执行(并且在每次操作后丢弃它们),而不是实例化非常大的集合。我想你可以构造一个简单的迭代器很难构建的情况。