什么时候使用Yield?

时间:2010-05-14 12:31:04

标签: c#

我什么时候应该使用收益率?什么时候才能使用回报?

6 个答案:

答案 0 :(得分:22)

返回可枚举时使用yield,并且此时没有所有结果。

实际上,当我想迭代大量信息(数据库,平面文件等)时,我已经使用了yield,而且我不想先将所有内容加载到内存中。 Yield是一种很好的方法,可以在不加载所有内容的情况下迭代块。

答案 1 :(得分:7)

收益率是迭代器。

它允许你处理小燕子中的列表,这对大型列表很有用。

关于Yield的神奇之处在于它会记住你在调用之间的位置。

如果您没有迭代,则不需要收益。

答案 2 :(得分:7)

yield关键字非常强大。它基本上允许您快速返回IEnumerableIEnumerator个对象,而无需对其进行明确编码。

考虑一个您想要返回两个IEnumerable对象的交集的场景。以下是使用yield关键字的方法。

public static class Program
{
  public static void Main()
  {
    IEnumerable<object> lhs = new List<int> { 1, 2, 3, 4, 5 };
    IEnumerable<object> rhs = new List<int> { 3, 4, 5, 6, 7 };
    foreach (object item in IntersectExample.Intersect(lhs, rhs))
    {
      Console.WriteLine(item);
      break;
    }
  }
}

public static class IntersectExample
{
  public static IEnumerable<object> Intersect(IEnumerable<object> lhs, IEnumerable<object> rhs)
  {
    var hashset = new HashSet<object>();
    foreach (object item in lhs)
    {
      if (!hashset.Contains(item))
      {
        hashset.Add(item);
      }
    }
    foreach (object item in rhs)
    {
      if (hashset.Contains(item))
      {
        yield return item;
      }
    }
  }
}

在你完全意识到发生了什么之前,很难理解这一点。通常,当您将两个集相交时,您将完成整个操作,然后将结果返回给调用者。这意味着操作的运行时复杂性为O(m + n),其中mn是要交叉的集合的大小,而不管您之后对结果执行的操作。但是,在我的例子中,我只是想从结果中挑选出第一个项目。使用IEnumerable关键字创建的yield可以非常轻松地延迟部分处理,直到实际需要为止。我的示例在O(m)中运行。另一种方法是对IEnumerable进行编码并手动维护其中的状态。 yield关键字的强大之处在于它为您创建了状态机。

答案 3 :(得分:6)

yield构造用于创建可以连续生成多个值的迭代器:

IEnumerable<int> three_numbers() {
    yield return 1;
    yield return 2;
    yield return 3;
}
...
foreach (var i in three_numbers()) {
    // i becomes 1, 2 and 3, in turn.
}

答案 4 :(得分:1)

Yield Return将从该点继续该方法。例如,您希望循环遍历数组或列表,并在此时返回每个元素以供调用者处理。所以你将使用收益率回报。如果你想返回所有内容然后完成,你不需要那样做

答案 5 :(得分:1)

这里解释:

C# Language Reference
yield (C# Reference)

调用的方法将返回每个值,以便调用者可以枚举它们。

这意味着当您想要迭代返回的每个可能结果时,您将需要使用 yield