Язык программирования C#9 и платформа .NET5
}Операции агрегирования LINQ
Запросы LINQ могут также проектироваться для выполнения над результирующим набором разнообразных операций агрегирования. Одним из примеров может служить расширяющий метод
. Другие возможности включают получение среднего, максимального, минимального или суммы значений с использованием членовCount(),Average(),Мах()либоMin()классаSum(). Вот простой пример:EnumerableHere 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). Вдобавок вы узнали, что определенная функциональность API-интерфейса LINQ to Objects доступна только через вызов расширяющих методов классаselect. В действительности при компиляции запросов LINQ компилятор C# транслирует все операции LINQ в вызовы методов классаEnumerable.EnumerableОгромное количество методов класса
прототипированы для приема делегатов в качестве аргументов. Многие методы требуют обобщенный делегат по имениEnumerable, который был описан во время рассмотрения обобщенных делегатов в главе 10. Взгляните на методFunс<>класса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)Делегат
представляет шаблон фиксированной функции с набором до 16 аргументов и возвращаемым значением. Если вы исследуете этот тип в браузере объектов Visual Studio, то заметите разнообразные формы делегатаFunc<>. Например: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>()Учитывая, что многие члены класса
при вызове ожидают получить делегат, можно вручную создать новый тип делегата и написать для него необходимые целевые методы, применить анонимный метод C# или определить подходящее лямбда-выражение. Независимо от выбранного подхода конечный результат будет одним и тем же.System.Linq.EnumerableХотя использование операций запросов LINQ является, несомненно, самым простым способом построения запросов LINQ, давайте взглянем на все возможные подходы, чтобы увидеть связь между операциями запросов C# и лежащим в основе типом
.EnumerableПостроение выражений запросов с применением операций запросов
Для начала создадим новый проект консольного приложения по имени
. В классеLinqUsingEnumerableбудут определены статические вспомогательные методы (вызываемые внутри операторов верхнего уровня) для иллюстрации разнообразных подходов к построению выражений запросов LINQ.ProgramПервый метод,
, предлагает наиболее прямолинейный способ создания выражений запросов и идентичен коду примераQueryStringsWithOperators(), который приводился ранее в главе:LinqOverArray