Why are ToLookup and GroupBy different?

.ToLookup<TSource, TKey> returns an ILookup<TKey, TSource>. ILookup<TKey, TSource> also implements interface IEnumerable<IGrouping<TKey, TSource>>.

.GroupBy<TSource, TKey> returns an IEnumerable<IGrouping<Tkey, TSource>>.

ILookup has the handy indexer property, so it can be used in a dictionary-like (or lookup-like) manner, whereas GroupBy can't. GroupBy without the indexer is a pain to work with; pretty much the only way you can then reference the return object is by looping through it (or using another LINQ-extension method). In other words, any case that GroupBy works, ToLookup will work as well.

All this leaves me with the question why would I ever bother with GroupBy? Why should it exist?

25308 次浏览

我为什么要为 GroupBy 操心? 它为什么要存在?

如果对一个表示包含10亿行的远程数据库表的对象调用 ToLookup,会发生什么情况?

数十亿行通过连接发送,然后在本地构建查找表。

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

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

当该查询对象被枚举时,将对表进行 在数据库服务器上分析,并将分组的结果一次发送回 随叫随到几个。

从逻辑上讲,它们是相同的东西,但是它们的 性能影响是完全不同的。调用 ToLookup 意味着 我要一个缓存,现在整个东西组织。调用 GroupBy 的意思是“我正在构建一个对象来表示这样一个问题: 如果我按照组来组织这些东西,它们看起来会是什么样子?'"

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

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

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

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