gpt4 book ai didi

c# - GroupBy 与 elementSelector 和 resultSelector

转载 作者:可可西里 更新时间:2023-11-01 03:09:06 25 4
gpt4 key购买 nike

Enumerable.GroupByQueryable.GroupBy扩展有 8 个重载。其中两个(对于 Enumerable.GroupBy )是:

// (a)
IEnumerable<TResult> GroupBy<TSource, TKey, TResult>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TKey, IEnumerable<TSource>, TResult> resultSelector);

// (b)
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);

(对于 Queryable.GroupBy 相同,只是用 Expression<Func<... 而不是 Func<... )

(b)还有一个 elementSelector作为参数。

在 MSDN 上是 an example for overload (a)an example for overload (b) .它们都使用相同的示例源集合:

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 }
};

示例 (a) 使用此查询:

var query = petsList.GroupBy(
pet => Math.Floor(pet.Age), // keySelector
(age, pets) => new // resultSelector
{
Key = age,
Count = pets.Count(),
Min = pets.Min(pet => pet.Age),
Max = pets.Max(pet => pet.Age)
});

示例 (b) 使用此查询:

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()
});

两次查询的结果完全一样。

问题 1:是否有任何一种我无法使用 resultSelector 表达的查询?一个人,我真正需要的地方 elementSelector ?或者这两个重载的功能是否总是等效的,使用其中一种方式只是个人喜好问题?

问题 2:使用 LINQ 查询语法时,这两种不同的重载是否对应?

(作为附带问题:将 Queryable.GroupBy 与 Entity Framework 一起使用时,两个重载是否会转换为完全相同的 SQL?)

最佳答案

对于 IEnumerable:

petsList.GroupBy(
pet => Math.Floor(pet.Age), // keySelector
(age, pets) => new // resultSelector
{
Key = age,
Count = pets.Count(),
Min = pets.Min(pet => pet.Age),
Max = pets.Max(pet => pet.Age)
});

相当于:

var query = petsList.GroupBy(
pet => Math.Floor(pet.Age), // keySelector
pet => pet, // elementSelector
(baseAge, ages) => new // resultSelector
{
Key = baseAge,
Count = ages.Count(),
Min = ages.Min(pet => pet.Age),
Max = ages.Max(pet => pet.Age)
});

使用 elementSelector 可以简化 resultSelector 中的表达式(比较下一个和上一个):

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(), //there is no lambda due to element selector
Max = ages.Max() ////there is no lambda due to element selector
});

在IQueryable中,就没那么简单了。您可以查看此方法的来源:

public static IQueryable<TResult> GroupBy<TSource, TKey, TElement, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> keySelector, Expression<Func<TSource, TElement>> elementSelector, Expression<Func<TKey, IEnumerable<TElement>, TResult>> resultSelector)
{
if (source == null)
throw Error.ArgumentNull("source");
if (keySelector == null)
throw Error.ArgumentNull("keySelector");
if (elementSelector == null)
throw Error.ArgumentNull("elementSelector");
if (resultSelector == null)
throw Error.ArgumentNull("resultSelector");
return source.Provider.CreateQuery<TResult>(
Expression.Call(
null,
((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TKey), typeof(TElement), typeof(TResult)),
new Expression[] { source.Expression, Expression.Quote(keySelector), Expression.Quote(elementSelector), Expression.Quote(resultSelector) }
));
}

public static IQueryable<TResult> GroupBy<TSource, TKey, TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>> keySelector,Expression<Func<TKey, IEnumerable<TSource>, TResult>> resultSelector)
{
if (source == null)
throw Error.ArgumentNull("source");
if (keySelector == null)
throw Error.ArgumentNull("keySelector");
if (resultSelector == null)
throw Error.ArgumentNull("resultSelector");
return source.Provider.CreateQuery<TResult>(
Expression.Call(
null,
((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TKey), typeof(TResult)),
new Expression[] { source.Expression, Expression.Quote(keySelector), Expression.Quote(resultSelector) }
));
}

如您所见,它们返回不同的表达式,因此我不确定结果 SQL 查询在所有情况下都相同,但我假设使用 elementSelector + resultSelector 重载的 SQL 查询将与没有 elementSelector 的重载相比不会慢。

答案 1:不,对于 IEnumerable,没有您不能单独使用 resultSelector 表达的查询。

答案 2。不,在使用 LINQ 查询语法时,没有对应的两种不同的重载。与 LINQ 查询语法相比,扩展方法具有更多可能性。

答案 3(附带问题):不保证对于此重载,sql 查询将相同。

关于c# - GroupBy 与 elementSelector 和 resultSelector,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14112230/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com