是否强制立即执行序列

本文关键字:执行 是否 | 更新日期: 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在评论中指出的,最后一段不准确)