ToLookup 是否强制立即执行序列

RBT*_*RBT 5 .net c# linq

我正在研究Enumerable.ToLookup API,它将可枚举序列转换为字典类型数据结构。更多详情可在这找到:

https://msdn.microsoft.com/en-us/library/system.linq.enumerable.tolookup(v=vs.110).aspx

它与ToDictionary API 的唯一区别是,如果键选择器导致重复键,它不会给出任何错误。我需要比较这两个 API 的延迟执行语义。据我所知,ToDictionary API 会导致立即执行序列,即它不遵循 LINQ 查询的延迟执行语义。谁能帮我解决ToLookup API 的延迟执行行为?它与ToDictionary API相同还是有一些区别?

spe*_*der 5

很容易测试...

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

回顾一下,ToLookup 贪婪地消耗源序列而不延迟。

相反,该GroupBy运算符延迟的,因此您可以编写以下内容而不会产生不良影响:

var groups = Inf().GroupBy(i => i / 100); //oops
Run Code Online (Sandbox Code Playgroud)

但是,GroupBy贪婪的,因此当您枚举时,整个源序列都会被消耗。

这意味着

groups.SelectMany(g=>g).First();
Run Code Online (Sandbox Code Playgroud)

也无法完成。

当您考虑分组问题时,很快就会发现,当将一个序列分成一系列组时,如果不完全消耗整个序列,就不可能知道其中一个组是否完整。