IEnumerable必须使用Yield才能延期吗

本文关键字:Yield IEnumerable | 更新日期: 2023-09-27 18:24:16

IEnumerable是否必须使用Yield才能延期?

以下是帮助我理解延迟执行和收益的测试代码。

 //immediate execution
        public IEnumerable Power(int number, int howManyToShow)
        {
            var result = new int[howManyToShow];
            result[0] = number;
            for (int i = 1; i < howManyToShow; i++)
                result[i] = result[i - 1] * number;
            return result;
        }
        //deferred but eager
        public IEnumerable PowerYieldEager(int number, int howManyToShow)
        {
            var result = new int[howManyToShow];
            result[0] = number;
            for (int i = 1; i < howManyToShow; i++)
                result[i] = result[i - 1] * number;
            foreach (var value in result)
                yield return value;
        }
        //deferred and lazy
        public IEnumerable PowerYieldLazy(int number, int howManyToShow)
        {
            int counter = 0;
            int result = 1;
            while (counter++ < howManyToShow)
            {
                result = result * number;
                yield return result;
            }
        }
        [Test]
        public void Power_WhenPass2AndWant8Numbers_ReturnAnEnumerable()
        {
            IEnumerable listOfInts = Power(2, 8);
            foreach (int i in listOfInts)
                Console.Write("{0} ", i);
        }

        [Test]
        public void PowerYieldEager_WhenPass2AndWant8Numbers_ReturnAnEnumerableOfInts()
        {
            //deferred but eager execution
            IEnumerable listOfInts = PowerYieldEager(2, 8);
            foreach (int i in listOfInts)
                Console.Write("{0} ", i);
        }

        [Test]
        public void PowerYield_WhenPass2AndWant8Numbers_ReturnAnEnumerableOfIntsOneAtATime()
        {
            //deferred and lazy execution
            IEnumerable listOfInts = PowerYieldLazy(2, 8);
            foreach (int i in listOfInts)
                Console.Write("{0} ", i);
        }

IEnumerable必须使用Yield才能延期吗

它不需要使用yield-最终您可以通过编写自定义枚举器(IEnumerator[<T>])并将操作延迟到第一个MoveNext()来完成yield所做的一切。然而,实施起来相当痛苦。当然,如果确实使用yield,则默认情况下实现是延迟的(您可以使用两种方法使其不延迟-一种不使用yield,然后访问数据后使用另一种方法(迭代器块)来实现枚举器。

坦率地说,编写枚举器既困难又麻烦。除非绝对必要,否则我会避免。迭代程序块非常棒。

返回IEnumerable的函数(F1)可以返回在另一个函数(F2)中计算的IEnumeraable,如果F2被延迟,则F1被延迟

例如,在下面的代码中,F1和F2都是延迟

public IEnumerable<int> F2()
{
    for (int i = 0; i < 10; i++) {
        yield return i;
    }
}
public IEnumerable<int> F1()
{
    return F2();
}
延迟和渴望是对立的——懒惰只是延迟的同义词。

渴望序列是预先计算的序列,例如列表或数组。延迟序列是指每当迭代时都要计算的序列。

在您的示例中,Power是热切的,因为它计算一个数组并返回它。这与PowerYieldEager不同,后者在迭代得到的IEnumerable之前不会构建数组。

您可以将延迟与渴望视为序列的潜力与序列的内容。考虑到这一点,yield return只是推迟的一种方式;当请求结果时计算的任何序列都是延迟序列。