Наша RPG-игра вышла в релиз, и серверы накопили огромный объём данных: списки игроков, логи сражений, инвентари, таблицы рекордов. Руководство хочет аналитику: кто из игроков набрал больше 1000 очков? Какие предметы самые популярные? Сколько сражений выиграл каждый маг?

У нас есть список игроков в виде List<Player>. Нужно отобрать только тех, у кого очки больше 1000, и отсортировать их по убыванию.

Задача: Напишите код, который из списка игроков выберет тех, у кого Score > 1000, отсортирует по убыванию очков и выведет их имена.

До сих пор для работы с коллекциями мы использовали циклы: foreach для перебора, if для фильтрации, временные списки для накопления результатов. Это работает, но при сложных запросах код быстро превращается в кашу из вложенных циклов и условий. LINQ предлагает другой подход.

Вот как выглядит решение задачи из «Разведки боем» с помощью LINQ:

using System;
using System.Linq;            // Подключаем LINQ
using System.Collections.Generic;

class Player
{
    public string Name { get; set; }
    public int Score { get; set; }
    public string Class { get; set; } // Маг, Воин, Лучник
}

class Program
{
    static void Main()
    {
        var players = new List<Player>
        {
            new Player { Name = "Альберт", Score = 2500, Class = "Маг" },
            new Player { Name = "Эдвард", Score = 800, Class = "Воин" },
            new Player { Name = "Мерлин", Score = 3100, Class = "Маг" },
            new Player { Name = "Элиза", Score = 1200, Class = "Лучник" },
            new Player { Name = "Фёдор", Score = 500, Class = "Воин" },
        };

        var topPlayers = players
            .Where(p => p.Score > 1000)           // Фильтрация
            .OrderByDescending(p => p.Score)       // Сортировка
            .ToList();

        foreach (var p in topPlayers)
            Console.WriteLine($"{p.Name}: {p.Score}");
    }
}

Три строки вместо десяти. Нет временных коллекций, нет ручной сортировки. Код читается почти как обычный текст: «из игроков выбери тех, у кого очки больше 1000, отсортируй по убыванию».

Если цикл foreach — это ручная сборка на конвейере (берёшь деталь, проверяешь, кладёшь в нужную коробку), то LINQ — это заказ на складе: «мне нужны все детали типа А, отсортированные по размеру». Склад сам разберётся, как выполнить заказ. LINQ работает с любым типом, реализующим интерфейс IEnumerable<T>. На практике это означает — с любой коллекцией:

Коллекция Работает с LINQ?
List<T> Да
Array (T[]) Да
Dictionary<K,V> Да (перебирает KeyValuePair)
HashSet<T> Да
string Да (перебирает char)

Чтобы использовать LINQ, нужно подключить пространство имён:

using System.Linq;

LINQ-методы можно выстраивать в цепочку — каждый метод принимает коллекцию и возвращает новую:

var result = players
    .Where(p => p.Score > 1000)          // Из 5 игроков осталось 3
    .OrderByDescending(p => p.Score)      // Отсортировали: 3100, 2500, 1200
    .Select(p => p.Name)                  // Взяли только имена
    .ToList();                             // Материализовали в List<string>

// result: ["Мерлин", "Альберт", "Элиза"]

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

LINQ (Language Integrated Query) — технология C#, позволяющая писать запросы к коллекциям в декларативном стиле. Вы описываете что хотите получить, а не как это сделать.

LINQ работает с любой коллекцией, реализующей IEnumerable<T>: списки, массивы, словари, множества.

LINQ-методы выстраиваются в цепочку, не изменяют исходную коллекцию и проверяются компилятором.

Для использования необходимо подключить using System.Linq;.

Обсуждение урока

0
Комментарии видны всем. Чтобы участвовать в обсуждении, войдите или зарегистрируйтесь.
Модерация сообщества

Пожаловаться на комментарий

Расскажите модераторам, что именно требует внимания.