Один объект удобно хранить в классе. Но как только объектов становится много, нужны коллекции: список заказов, словарь статусов, фильтрация, сумма, выборка. В C# для этого часто используют List<T>, Dictionary<TKey, TValue> и LINQ
В этом уроке мы возьмем список заказов и ответим на практические вопросы: какие заказы оплачены, сколько денег они принесли и как красиво вывести названия клиентов
Что получится в конце
Программа выведет:
Оплаченные заказы:
- Алия: 2400
- Тимур: 900
Сумма оплаченных заказов: 3300
Статус 2: Оплачен
Создаем проект
dotnet new console -n CSharpLinq
cd CSharpLinq
Вставьте в Program.cs:
var orders = new List<Order>
{
new("Алия", 2400m, true),
new("Ильдар", 1200m, false),
new("Тимур", 900m, true)
};
var statusNames = new Dictionary<int, string>
{
[1] = "Новый",
[2] = "Оплачен",
[3] = "Отменен"
};
var paidOrders = orders.Where(order => order.IsPaid).ToList();
var paidTotal = paidOrders.Sum(order => order.Total);
Console.WriteLine("Оплаченные заказы:");
foreach (var order in paidOrders)
{
Console.WriteLine($"- {order.Customer}: {order.Total}");
}
Console.WriteLine($"Сумма оплаченных заказов: {paidTotal}");
Console.WriteLine($"Статус 2: {statusNames[2]}");
public record Order(string Customer, decimal Total, bool IsPaid);
Запустите:
dotnet run
Что такое List
List<Order> — это список объектов типа Order:
var orders = new List<Order>
{
new("Алия", 2400m, true),
new("Ильдар", 1200m, false),
new("Тимур", 900m, true)
};
В отличие от массива, List удобно пополнять:
orders.Add(new Order("Мария", 1500m, true));
Список используют, когда порядок важен или когда нужно пройтись по набору элементов
Что такое Dictionary
Dictionary<int, string> хранит пары ключ-значение:
var statusNames = new Dictionary<int, string>
{
[1] = "Новый",
[2] = "Оплачен",
[3] = "Отменен"
};
Получить значение можно по ключу:
Console.WriteLine(statusNames[2]);
Для справочника статусов это удобно: есть код статуса и человекочитаемое название
Но если ключа нет, statusNames[99] выбросит исключение. Безопаснее:
if (statusNames.TryGetValue(99, out var status))
{
Console.WriteLine(status);
}
Where, Select, Sum
LINQ позволяет читать операции над коллекциями почти как цепочку действий:
var paidOrders = orders.Where(order => order.IsPaid).ToList();
Where оставляет только элементы, которые подходят условию
Select преобразует элементы:
var customerNames = orders.Select(order => order.Customer).ToList();
Sum считает сумму:
var paidTotal = paidOrders.Sum(order => order.Total);
Это не отдельный язык внутри C#, а набор методов для работы с последовательностями
Почему ToList не всегда нужен
Многие LINQ-операции выполняются лениво. Запрос:
var paidOrders = orders.Where(order => order.IsPaid);
еще не обязательно прошел по списку. Перебор начнется, когда вы используете результат в foreach, ToList, Sum и похожих операциях
Для новичка хорошее правило такое: если нужно сохранить результат как список и пройтись по нему несколько раз, используйте ToList(). Если просто считаете Sum, отдельный ToList может быть не нужен:
var paidTotal = orders
.Where(order => order.IsPaid)
.Sum(order => order.Total);
Частые ошибки
The type or namespace name 'List' could not be found. Добавьте using System.Collections.Generic;, если проект не подключил его автоматически
Sequence contains no elements. Часто возникает с First() на пустой коллекции. Для безопасного варианта используйте FirstOrDefault()
KeyNotFoundException. В Dictionary нет такого ключа. Используйте TryGetValue
LINQ-цепочка стала нечитаемой. Разбейте ее на несколько переменных с понятными именами
Что может быть еще интересно по этой теме
LINQ заменяет циклы? Нет. Он удобен для фильтрации, выборки и агрегации, но обычный foreach часто читабельнее для сложной пошаговой логики
List или массив? Для учебных и прикладных сценариев чаще начинайте с List<T>. Массив хорош, когда размер фиксирован и важна простота структуры
Dictionary всегда быстрее List? Для поиска по ключу обычно удобнее и быстрее. Но если нужен порядок или перебор всех элементов, список может быть естественнее
Почему record вместо class? record удобно использовать для маленьких моделей данных. Классы никуда не исчезают; просто для примера заказа record короче
Что открыть дальше
- Классы и свойства в C#: первый пример — если модель
Orderпока выглядит непривычно. - async await в C#: первый пример без магии — следующий важный синтаксис современного C#.
- JSON и файлы в C#: читаем настройки проекта — коллекции часто сериализуют в JSON.
- ASP.NET Core Minimal API: первый endpoint — LINQ пригодится при подготовке ответов API.



