是否强制立即执行序列
本文关键字:执行 是否 | 更新日期: 2023-09-27 18:02:10
我正在查找Enumerable。tollookup API,将可枚举序列转换为字典类型的数据结构。更多细节可在这里找到:
https://msdn.microsoft.com/en-us/library/system.linq.enumerable.tolookup (v = vs.110) . aspx
它与ToDictionary API的唯一区别是,如果键选择器导致重复键,它不会给出任何错误。我需要比较这两个api的延迟执行语义。据我所知,ToDictionary API导致序列立即执行,即它不遵循LINQ查询的延迟执行语义。谁能帮助我与延迟执行行为的 tollookup API?它是否与ToDictionary API相同或有一些差异?
很容易测试…
void Main()
{
var lookup = Inf().ToLookup(i => i / 100);
Console.WriteLine("if you see this, ToLookup is deferred"); //never happens
}
IEnumerable<int> Inf()
{
unchecked
{
for(var i=0;;i++)
{
yield return i;
}
}
}
概括地说,ToLookup
贪婪地不延迟地消耗源序列。
相反,GroupBy
操作符是延迟的,因此您可以编写以下代码而不会产生不良影响:
var groups = Inf().GroupBy(i => i / 100); //oops
然而,GroupBy
是贪婪的,所以当你枚举时,整个源序列被消耗。
这意味着
groups.SelectMany(g=>g).First();
也无法完成。
当您考虑分组问题时,很快就会发现,当将一个序列分成一系列组时,如果不完全使用整个序列,甚至不可能知道其中一个组是否完整。
这在这里有点覆盖,但很难找到!
简而言之——tollookup不会延迟执行!
- tollookup() ->立即执行
- GroupBy()(和其他查询方法)->延迟执行
如果您查看enumerable. todictionary()和enumerable. tollookup()方法的参考实现源代码,您将看到它们最终都在源枚举对象上执行foreach
循环。这是确认源可枚举对象的执行在两种情况下都没有延迟的一种方法。
但是我的意思是,答案是不言自明的,如果你从一个可枚举对象开始,函数的返回值不再是一个可枚举对象,那么很明显,它一定已经被执行(消耗)了,不是吗?
(正如@spender在评论中指出的,最后一段不准确)