为什么ToLookup和GroupBy不同?

.ToLookup<TSource, TKey>返回一个ILookup<TKey, TSource>ILookup<TKey, TSource>还实现了接口IEnumerable<IGrouping<TKey, TSource>>

.GroupBy<TSource, TKey>返回IEnumerable<IGrouping<Tkey, TSource>>

ILookup具有方便的索引器属性,所以它可以像字典一样使用(或者查找),而GroupBy不能。 Group没有索引器是一个痛苦的工作; 几乎所有可以引用返回对象的唯一方法是循环(或使用其他LINQ扩展方法)。 换句话说,任何GroupBy工作的情况下,ToLookup都可以工作。

所有这些都让我想起了为什么我会打扰GroupBy? 为什么它存在?

为什么我会打扰GroupBy? 为什么它存在?

当你调用ToLookup来表示一个有十亿行的远程数据库表时,会发生什么?

十亿行通过线路发送,并在本地build立查找表。

在这样的对象上调用GroupBy会发生什么?

查询对象被build立; 故事结局。

当查询对象被枚举时,表的分析在数据库服务器上完成并且分组的结果每次按需发送一次。

从逻辑上讲,它们是相同的东西,但每个的性能影响是完全不同的。 调用ToLookup意味着我现在需要caching整个组织的整个事情 。 调用GroupBy意味着“我正在构build一个对象来表示这个问题”如果我按组来组织它们,这些事情会是什么样子?“

在简单的LINQ世界的话:

  • ToLookup() – 立即执行
  • GroupBy() – 延迟执行

这两者是相似的,但用于不同的场景。 .ToLookup()返回一个准备使用的对象,该对象已经拥有所有的组(而不是组的内容)。 另一方面.GroupBy()返回一个惰性加载的组序列。

不同的LINQ提供程序可能会有不同的行为,以便对组进行加载和延迟加载。 使用LINQ到对象可能没什么区别,但是对于LINQ到SQL(或LINQ到EF等),分组操作是在数据库服务器而不是客户端上执行的,因此您可能需要对组密钥进行额外的过滤(生成一个HAVING子句),然后只获得一些组而不是所有的组。 .ToLookup()不允许这样的语义,因为所有的项目都是热切的分组。