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);
}
它不需要使用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
只是推迟的一种方式;当请求结果时计算的任何序列都是延迟序列。