0Pricing
C# Academy · Урок

Агрегаты и ToList

Подсчитывайте, суммируйте и материализуйте данные

«Агрегаты и ToList» — бесплатный урок C# Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C# Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C# Academy содержит 4 уроков всего.

Подсчёт элементов

Count возвращает количество элементов в последовательности. С условием он подсчитывает только подходящие элементы.

Этот оператор принудительно запускает перебор, поэтому для получения итога обрабатывается вся последовательность — это операция агрегирования.

using System;
using System.Linq;

int[] nums = { 1, 2, 3, 4, 5 };
Console.WriteLine(nums.Count());
Console.WriteLine(nums.Count(n => n > 2));

Суммирование значений

Sum складывает числовые значения. Для числовой последовательности он суммирует элементы, а с селектором — выбранное значение каждого элемента.

Результат имеет тот же числовой тип, что и источник или результат селектора.

using System;
using System.Linq;
using System.Collections.Generic;

record Order(int Qty, decimal Price);
var orders = new List<Order> { new(2, 5m), new(3, 4m) };
decimal total = orders.Sum(o => o.Qty * o.Price);
Console.WriteLine(total);

Вычисление среднего значения

Average вычисляет среднее арифметическое. Как и Sum, он принимает необязательный селектор.

Результат имеет тип с плавающей точкой, например double, даже если источник содержит целые числа, поэтому при делении точность не теряется.

using System;
using System.Linq;

int[] scores = { 80, 90, 100 };
double avg = scores.Average();
Console.WriteLine(avg);

Минимум и максимум

Min и Max возвращают наименьшее и наибольшее значения. С селектором они выбирают минимальный или максимальный ключ из преобразованных данных.

В современных версиях .NET MaxBy и MinBy возвращают весь элемент с экстремальным ключом, а не только значение ключа.

using System;
using System.Linq;
using System.Collections.Generic;

record P(string Name, int Age);
var ps = new List<P> { new("Ana", 30), new("Bo", 22) };
var oldest = ps.MaxBy(p => p.Age);
Console.WriteLine(oldest!.Name);

Проблемы с пустой последовательностью

Для пустой последовательности Average, Min и Max над типами-значениями выбрасывают исключение InvalidOperationException. Sum возвращает ноль, а Count — ноль.

Проверяйте данные с помощью Any() или используйте DefaultIfEmpty перед вычислением среднего для потенциально пустых данных.

using System;
using System.Linq;

int[] empty = Array.Empty<int>();
double avg = empty.DefaultIfEmpty(0).Average();
Console.WriteLine(avg);

Aggregate для пользовательских свёрток

Aggregate сворачивает последовательность в одно значение с помощью функции накопления. Это общий вариант операций, лежащих в основе Sum и других операторов.

Вы можете задать начальное значение и объединять с ним каждый элемент, получая промежуточный результат. Это удобно для вычисления произведений, объединения строк и пользовательской логики.

using System;
using System.Linq;

int[] nums = { 1, 2, 3, 4 };
int product = nums.Aggregate(1, (acc, n) => acc * n);
Console.WriteLine(product);

Материализация с помощью ToList

ToList немедленно выполняет запрос и копирует результаты в объект List<T>. Это намеренно прекращает отложенное выполнение.

Используйте его, чтобы получить стабильный снимок данных, не запускать ресурсоёмкий конвейер повторно или воспользоваться возможностями списка, например индексацией и свойством Count.

using System;
using System.Linq;

int[] nums = { 1, 2, 3, 4 };
var evens = nums.Where(n => n % 2 == 0).ToList();
evens.Add(6);
Console.WriteLine(string.Join(", ", evens));

ToArray и ToDictionary

К связанным методам материализации относятся ToArray для массива фиксированного размера и ToDictionary для поиска по ключу.

ToDictionary принимает селектор ключа и необязательный селектор значения, а затем выбрасывает исключение, если два элемента дают один и тот же ключ.

using System;
using System.Linq;
using System.Collections.Generic;

record P(string Name, int Age);
var ps = new List<P> { new("Ana", 30), new("Bo", 22) };
var byName = ps.ToDictionary(p => p.Name, p => p.Age);
Console.WriteLine(byName["Ana"]);

Зачем материализовать данные

Отложенные запросы запускаются заново при каждом переборе. Если конвейер ресурсоёмкий или читает изменяющийся источник, это приводит к ошибкам и замедлению работы.

Однократный вызов ToList сохраняет результаты, поэтому последующие чтения выполняются быстро и дают согласованные данные.

using System;
using System.Linq;

int runs = 0;
int[] nums = { 1, 2, 3 };
var list = nums.Select(n => { runs++; return n; }).ToList();
foreach (var _ in list) { }
foreach (var _ in list) { }
Console.WriteLine(runs);

First, один элемент и Any

Операторы получения элементов также запускают выполнение. First возвращает первое совпадение и выбрасывает исключение, если совпадений нет; FirstOrDefault вместо этого возвращает значение по умолчанию, а Single требует ровно один элемент.

Any сообщает, есть ли в последовательности хотя бы один подходящий элемент, не перебирая все элементы для подсчёта.

using System;
using System.Linq;

int[] nums = { 3, 8, 5, 12 };
int firstBig = nums.First(n => n > 7);
bool hasOdd = nums.Any(n => n % 2 == 1);
Console.WriteLine($"{firstBig} {hasOdd}");

Полный конвейер

В реальных запросах объединяются фильтрация, формирование нужной структуры данных, сортировка и агрегирование, часто с завершением методом материализации.

Читайте запрос сверху вниз: отфильтруйте данные, сформируйте их структуру, отсортируйте и соберите результат. Итоговый ToList запускает весь конвейер один раз.

using System;
using System.Linq;
using System.Collections.Generic;

record Sale(string City, int Amt);
var sales = new List<Sale> { new("NY", 5), new("LA", 3), new("NY", 9) };
var top = sales.Where(s => s.Amt > 4)
               .OrderByDescending(s => s.Amt)
               .Select(s => s.City)
               .ToList();
Console.WriteLine(string.Join(", ", top));

Быстрая проверка

Подумайте об отложенном выполнении и материализации.

Повторение

Агрегаты сводят последовательность к одному значению: Count, Sum, Average, Min/Max, MinBy/MaxBy и общий Aggregate. Они запускают выполнение и могут выбрасывать исключения для пустых источников.

ToList, ToArray и ToDictionary материализуют результаты, прекращая отложенное выполнение, поэтому ресурсоёмкий конвейер запускается один раз. На этом завершается набор инструментов LINQ для фильтрации и формирования результатов.

Часто задаваемые вопросы

Урок «Агрегаты и ToList» бесплатный?

Да — полный текст урока «Агрегаты и ToList» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C# Academy, подпишись на CoddyKit PRO. Курс C# Academy содержит 4 уроков всего.

Чему я научусь в уроке «Агрегаты и ToList»?

Подсчитывайте, суммируйте и материализуйте данные Ты практикуешь C# Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать C# Academy?

Предыдущий опыт не требуется. C# Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «Агрегаты и ToList»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке C# Academy?

Да. Каждый урок C# Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. WHERE и фильтрация
  2. SELECT и проекция
  3. OrderBy и группировка
  4. Агрегаты и ToList
← Назад к C# Academy