在C#中理解产量问题

这个问题在这里已经有了答案:

  • 在C#中使用的yield关键字是什么? 16个答案

  • 这被称为延迟执行, yield是懒惰的,只会按需要工作。

    这具有很多优点,其中之一就是您可以创建看似无限的枚举:

    public IEnumerable<int> InfiniteOnes()
    {
         while (true)
             yield 1;
    }
    

    现在想象一下:

    var infiniteOnes = InfiniteOnes();
    

    会急切地执行,你会非常高兴地发现一个StackOverflow异常。

    另一方面,因为懒惰,你可以做到以下几点:

    var infiniteOnes = InfiniteOnes();
    //.... some code
    foreach (var one in infiniteOnes.Take(100)) { ... }
    

    然后,

    foreach (var one in infiniteOnes.Take(10000)) { ... }
    

    迭代器块将只在需要时运行; 当枚举被迭代时,不在之前,不在之后。


    从msdn:

    延期执行

    延迟执行意味着对表达式的评估会延迟到实际需要实现的值。 当您必须处理大型数据集时,延迟执行可以大大提高性能,特别是在包含一系列链式查询或操作的程序中。 在最好的情况下,延迟执行只能通过源集合进行一次迭代。

    在迭代器块中使用时,yield关键字(以yield-return语句的形式)直接在C#语言中支持延迟执行。 这样的迭代器必须返回IEnumeratorIEnumerator<T>类型的集合(或派生类型)。

    var vendorIterator = repository.RetrieveWithIterator(); // <-- Lets deferred the execution
    foreach (var item in vendorIterator) // <-- execute it because we need it
    {
        Debug.WriteLine(item);
    }
    var actual = vendorIterator.ToList();
    

    渴望与懒惰评估

    当你编写一个实现延迟执行的方法时,你还必须决定是否使用延迟评估或急切评估来实现该方法。

  • 在惰性评估中,每次调用迭代器时都会处理源集合中的单个元素。 这是迭代器实现的典型方式。
  • 在急切的评估中,第一次调用迭代器将导致整个集合被处理。 源集合的临时副本也可能需要。
  • 懒惰评估通常会产生更好的性能,因为它在整个集合评估过程中平均分配开销处理,并最大限度地减少临时数据的使用。 当然,对于一些操作来说,除了实现中间结果之外没有别的选择。

    资源


    当你在需要的时候循环它们会得到物品。 这样说你只需要前4个结果,然后你就破了,它不会再产生任何东西,你只是保存了一些处理能力!

    来自MS Docs:

    您使用yield return语句一次返回一个元素。 您可以使用foreach语句或LINQ查询来使用迭代器方法。 foreach循环的每次迭代调用迭代器方法。 在迭代器方法中达到yield return语句时,将返回expression,并保留代码中的当前位置。 下一次调用迭代器函数时,将从该位置重新启动执行。 您可以使用yield break语句结束迭代。

    注意 - 如果您对.ToList()方法产生结果,它将像您返回单个列表一样工作,从而破坏了yield的目的。

    链接地址: http://www.djcxy.com/p/9089.html

    上一篇: Trouble understanding yield in C#

    下一篇: Where it is preferred to use yield return in c#?