}
Операции агрегирования LINQ
Запросы LINQ могут также проектироваться для выполнения над результирующим набором разнообразных операций агрегирования. Одним из примеров может служить расширяющий метод
Count()
. Другие возможности включают получение среднего, максимального, минимального или суммы значений с использованием членов
Average()
,
Мах()
,
Min()
либо
Sum()
класса
Enumerable
. Вот простой пример:
Here is a simple example:static void AggregateOps()
{
double[] winterTemps = { 2.0, -21.3, 8, -4, 0, 8.2 };
// Разнообразные примеры агрегации.
// Выводит максимальную температуру:
Console.WriteLine("Max temp: {0}",
(from t in winterTemps select t).Max());
// Выводит минимальную температуру:
Console.WriteLine("Min temp: {0}",
(from t in winterTemps select t).Min());
// Выводит среднюю температуру:
Console.WriteLine("Average temp: {0}",
(from t in winterTemps select t).Average());
// Выводит сумму всех температур:
Console.WriteLine("Sum of all temps: {0}",
(from t in winterTemps select t).Sum());
}
Приведенные примеры должны предоставить достаточный объем сведений, чтобы вы освоились с процессом построения выражений запросов LINQ. Хотя существуют дополнительные операции, которые пока еще не рассматривались, вы увидите примеры позже в книге, когда речь пойдет о связанных технологиях LINQ. В завершение вводного экскурса в LINQ оставшиеся материалы главы посвящены подробностям отношений между операциями запросов LINQ и лежащей в основе объектной моделью.
Внутреннее представление операторов запросов LINQ
К настоящему моменту вы уже знакомы с процессом построения выражений запросов с применением разнообразных операций запросов C# (таких как
from
,
in
,
where
,
orderby
и
select
). Вдобавок вы узнали, что определенная функциональность API-интерфейса LINQ to Objects доступна только через вызов расширяющих методов класса
Enumerable
. В действительности при компиляции запросов LINQ компилятор C# транслирует все операции LINQ в вызовы методов класса
Enumerable
.
Огромное количество методов класса
Enumerable
прототипированы для приема делегатов в качестве аргументов. Многие методы требуют обобщенный делегат по имени
Funс<>
, который был описан во время рассмотрения обобщенных делегатов в главе 10. Взгляните на метод
Where()
класса
Enumerable
, вызываемый автоматически в случае использования операции
where
:
<b>// Перегруженные версии метода Enumerable.Where<T>().</b>
<b>// Обратите внимание, что второй параметр имеет тип System.Func<>.</b>
public static IEnumerable<TSource> Where<TSource>(
this IEnumerable<TSource> source,
System.Func<TSource,int,bool> predicate)
public static IEnumerable<TSource> Where<TSource>(
this IEnumerable<TSource> source,
System.Func<TSource,bool> predicate)
Делегат
Func<>
представляет шаблон фиксированной функции с набором до 16 аргументов и возвращаемым значением. Если вы исследуете этот тип в браузере объектов Visual Studio, то заметите разнообразные формы делегата
Func<>
. Например:
<b>// Различные формы делегата Func<>.</b>
public delegate TResult Func<T1,T2,T3,T4,TResult>
(T1 arg1, T2 arg2, T3 arg3, T4 arg4)
public delegate TResult Func<T1,T2,T3,TResult>(T1 arg1, T2 arg2, T3 arg3)
public delegate TResult Func<T1,T2,TResult>(T1 arg1, T2 arg2)
public delegate TResult Func<T1,TResult>(T1 arg1)
public delegate TResult Func<TResult>()
Учитывая, что многие члены класса
System.Linq.Enumerable
при вызове ожидают получить делегат, можно вручную создать новый тип делегата и написать для него необходимые целевые методы, применить анонимный метод C# или определить подходящее лямбда-выражение. Независимо от выбранного подхода конечный результат будет одним и тем же.
Хотя использование операций запросов LINQ является, несомненно, самым простым способом построения запросов LINQ, давайте взглянем на все возможные подходы, чтобы увидеть связь между операциями запросов C# и лежащим в основе типом
Enumerable
.
Построение выражений запросов с применением операций запросов
Для начала создадим новый проект консольного приложения по имени
LinqUsingEnumerable
. В классе
Program
будут определены статические вспомогательные методы (вызываемые внутри операторов верхнего уровня) для иллюстрации разнообразных подходов к построению выражений запросов LINQ.
Первый метод,
QueryStringsWithOperators()
, предлагает наиболее прямолинейный способ создания выражений запросов и идентичен коду примера
LinqOverArray
, который приводился ранее в главе: