![](/img/trans.png)
[英]How to use a Factory method as resultSelector in LINQ Join
[英]What are the uses for Linq's GroupBy method with resultselector overload?
在MSDN上,我发现Enumerable.GroupBy方法的以下重载:
public static IEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TSource, TElement> elementSelector,
Func<TKey, IEnumerable<TElement>, TResult> resultSelector)
以及以下示例:
List<Pet> petsList =
new List<Pet>{ new Pet { Name="Barley", Age=8.3 },
new Pet { Name="Boots", Age=4.9 },
new Pet { Name="Whiskers", Age=1.5 },
new Pet { Name="Daisy", Age=4.3 } };
var query = petsList.GroupBy(
pet => Math.Floor(pet.Age), //keySelector
pet => pet.Age, //elementSelector
(baseAge, ages) => new //resultSelector
{
Key = baseAge,
Count = ages.Count(),
Min = ages.Min(),
Max = ages.Max()
});
尽管我了解此代码的工作原理,但我无法想到它的实际用法。 正如我现在看到的那样,这将返回一个Enumerable
,其代码末尾定义了匿名类型的元素。 但是,为什么GroupBy方法会返回未分组的枚举? 不能通过使用Select,OrderBy等来完成? 还是此重载的主要目的是自己定义Dictionary
作为TResult
一部分?
以下两个查询将产生相同的结果。
var queryA = source
.GroupBy(x => x.Id)
.Select(g => new { Id = g.Key, Count = g.Count() });
var queryB = source
.GroupBy(x => x.Id, (key, g) => new { Id = key, Count = g.Count() });
不同之处在于,第一个查询必须为每个组实例化IGrouping<TKey, TElement>
,而第二个查询则不必。 在这种情况下,您应该首选queryB
。
是的,它没有执行Select()
无法完成的任何操作。 我们甚至可以将其实现为:
public static IEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<TKey, IEnumerable<TElement>, TResult> resultSelector)
{
return source.GroupBy(keySelector, elementSelector).Select(grp => resultSelector(grp.Key, grp));
}
/* Repeat in Queryable for IQueryable */
但是,首先,它不是以这种方式实现的,并且这种相对常见的情况得到了更有效的处理。
其次,我怀疑更大的影响力(但不能肯定地说)是IQueryable
版本类似于许多SQL组构造。 确实,对于SQL的GROUP BY
,在大多数情况下,我们必须将聚合函数与未包含在GROUP BY
中的那些选定项目一起使用。 考虑:
SELECT FLOOR(age), COUNT(ALL age), MIN(age), MAX(age)
FROM Pets
GROUP BY FLOOR(age)
这几乎等同于您引用的示例中基于列表的操作。
因此,有意义的是让Queryable.GroupBy()
重载带有resultSelector
参数,并且当它们在Queryable
作用于IQueryable
,相应的方法必须在Enumerable
作用于IEnumerable
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.