128

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

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

ILookup 具有方便的索引器属性,因此它可以以类似字典(或类似查找)的方式使用,而 GroupBy 不能。没有索引器的 GroupBy 使用起来很痛苦;几乎唯一可以引用返回对象的方法是循环遍历它(或使用另一种 LINQ 扩展方法)。换句话说,任何 GroupBy 工作的情况,ToLookup 也能工作。

所有这一切都给我留下了一个问题,我为什么要打扰 GroupBy?为什么它应该存在?

4

3 回答 3

199

我为什么要打扰 GroupBy?为什么它应该存在?

当您对一个表示包含十亿行的远程数据库表的对象调用 ToLookup 时会发生什么?

十亿行通过网络发送,您在本地构建查找表。

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

构建了一个查询对象;故事结局。

当枚举该查询对象时,然后在数据库服务器上完成对表的分析,并且一次根据需要将分组结果发送回几个。

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

于 2012-04-18T18:22:03.640 回答
112

用简单的 LINQ 世界的话来说:

  • ToLookup()- 立即执行
  • GroupBy()- 延期执行
于 2012-08-15T12:46:47.037 回答
19

两者相似,但用于不同的场景。.ToLookup()返回一个准备好使用的对象,该对象已经急切地加载了所有组(但不是组的内容)。另一方面,.GroupBy()返回延迟加载的组序列。

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

于 2012-04-18T18:24:26.830 回答