最后编辑:
我选择了Timothy的答案,但如果您想要一个利用 C# yield语句的更可爱的实现,请查看Eamon的答案:https ://stackoverflow.com/a/19825659/145757
默认情况下, LINQ查询是延迟流式传输的。
ToArray
/ToList
提供完整的缓冲,但首先他们很渴望,其次可能需要相当长的时间才能完成无限序列。
有没有办法结合这两种行为:在生成时动态流式传输和缓冲值,以便下一次查询不会触发已经查询的元素的生成。
这是一个基本用例:
static IEnumerable<int> Numbers
{
get
{
int i = -1;
while (true)
{
Console.WriteLine("Generating {0}.", i + 1);
yield return ++i;
}
}
}
static void Main(string[] args)
{
IEnumerable<int> evenNumbers = Numbers.Where(i => i % 2 == 0);
foreach (int n in evenNumbers)
{
Console.WriteLine("Reading {0}.", n);
if (n == 10) break;
}
Console.WriteLine("==========");
foreach (int n in evenNumbers)
{
Console.WriteLine("Reading {0}.", n);
if (n == 10) break;
}
}
这是输出:
Generating 0.
Reading 0.
Generating 1.
Generating 2.
Reading 2.
Generating 3.
Generating 4.
Reading 4.
Generating 5.
Generating 6.
Reading 6.
Generating 7.
Generating 8.
Reading 8.
Generating 9.
Generating 10.
Reading 10.
==========
Generating 0.
Reading 0.
Generating 1.
Generating 2.
Reading 2.
Generating 3.
Generating 4.
Reading 4.
Generating 5.
Generating 6.
Reading 6.
Generating 7.
Generating 8.
Reading 8.
Generating 9.
Generating 10.
Reading 10.
生成代码被触发 22 次。
我希望它被触发 11 次,第一次迭代可枚举。
然后第二次迭代将受益于已经生成的值。
它会是这样的:
IEnumerable<int> evenNumbers = Numbers.Where(i => i % 2 == 0).Buffer();
对于熟悉Rx的人来说,这是一种类似于ReplaySubject
.