为什么ToLookup和GroupBy不同?


110

.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?为什么要存在?


7
GroupByIQuerableILookup不是
Magnus 2012年

5
GroupBy不会枚举列表ToLookup会以ToList / ToArray的相同方式枚举
Aducci 2012年

3
我之所以提名它重新开放是因为据称它与IGrouping有关,而不是关于IGrouping而不是GroupByILookup而不是ToLookup。它们之间的差异不同于它们之间的差异。从问题之间答案的差异中应该可以明显看出这一点。
2015年

1
他们两个都创建一个Lookup,但是GroupBy在枚举结果时创建了referencesource.microsoft.com/#System.Core/System/Linq/…–
Slai

Answers:


175

为什么我要麻烦GroupBy?为什么要存在?

当您在表示其中有十亿行的远程数据库表的对象上调用ToLookup时,会发生什么情况?

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

当您在此类对象上调用GroupBy时会发生什么?

建立查询对象;故事结局。

枚举该查询对象后,将在数据库服务器上对表进行分析,并将分组结果一次按需发送回一些。

从逻辑上讲,它们是同一件事,但是每个组件的性能含义完全不同。调用ToLookup意味着我想要按组现在组织的整个事情的缓存。调用GroupBy的意思是“我正在构建一个对象来表示问题:如果按组组织这些事情,这些事情会是什么样?”


6
张贴者没有专门针对IQueryable<T>陈述。您的答案涵盖了这种情况,但是当它只是普通语言IEnumerable<T>(LINQ-to-Objects)时,似乎没有理由在另一个之上使用它,这就是我相信@Shlomo试图达到的目的。 不是这种IQueryable<T>情况,而是LINQ-to-Objects情况。
casperOne 2012年

21
@casperOne:我认为您没有理解我的观点。即使在LINQ到对象的情况下,调用GroupBy 仍然不会在集合上进行迭代。(正如Aducci在删除的答案中指出的那样。)这是根本的区别。
埃里克·利珀特

12
@EricLippert:但是,这仅仅是实现的一个副作用,还是保证无论您对实现进行了什么更改,都可以在调用ToLookup时对可枚举进行迭代?

9
@Will:你说得很对;该文档不保证ToLookup是“渴望的”。它可能应该注意。
埃里克·利珀特

10
渴望的解释。我认为“ ToMetaType”的语言暗示着渴望;尽管显然要由实施来决定。其他的“收件人”都很渴望(ToList,ToArray,ToDictionary)。多谢你们。
Shlomo

97

用简单的LINQ世界字来说:

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

17

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

不同的LINQ提供程序对于组的渴望和延迟加载可能具有不同的行为。使用LINQ-to-Object可能几乎没有什么区别,但是使用LINQ-to-SQL(或LINQ-to-EF等),分组操作是在数据库服务器而不是客户端上执行的,因此您可能需要对组键(生成HAVING子句)进行其他过滤,然后仅获取部分组而不是全部。.ToLookup()因为所有项目都被热切地分组,所以不允许这种语义。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.