为什么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()
不允许这样的语义,因为所有的项目都是热切的分组。