Ответ
В LINQ (Language Integrated Query) можно выделить типы по синтаксису написания и по источнику данных.
1. Типы по синтаксису
a) Синтаксис запросов (Query Syntax)
Напоминает SQL, использует ключевые слова from, where, select, group by, orderby и т.д.
// Пример: выборка и сортировка
var query = from product in products
where product.Price > 100 && product.Category == "Electronics"
orderby product.Price descending
select new { product.Name, product.Price };
Плюсы: Читаемость для сложных операций соединения (join) и группировки.
Минусы: Поддерживает не все операторы LINQ.
b) Синтаксис методов (Method Syntax / Fluent Syntax)
Использует цепочки методов расширения (Where, Select, OrderBy), основанные на лямбда-выражениях.
// Тот же запрос в синтаксисе методов
var query = products
.Where(p => p.Price > 100 && p.Category == "Electronics")
.OrderByDescending(p => p.Price)
.Select(p => new { p.Name, p.Price });
Плюсы: Более гибкий, поддерживает все операторы LINQ, компактный для простых запросов. Минусы: Цепочки могут стать длинными и менее читаемыми.
Важно: Оба синтаксиса компилируются в одинаковый IL-код. Их можно комбинировать в одном запросе.
2. Типы по источнику данных (технологии LINQ)
a) LINQ to Objects
Работает с любыми коллекциями в памяти, реализующими IEnumerable<T>.
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
var evenNumbers = numbers.Where(n => n % 2 == 0).ToList();
b) LINQ to Entities (ранее LINQ to SQL)
Используется с Entity Framework Core. Запросы транслируются в SQL и выполняются на стороне базы данных.
// DbContext - часть Entity Framework Core
using var db = new AppDbContext();
var users = await db.Users
.Where(u => u.IsActive)
.OrderBy(u => u.LastName)
.ToListAsync(); // Генерирует и выполняет SQL
c) LINQ to XML
Предоставляет удобный API для работы с XML-документами.
XDocument doc = XDocument.Load("data.xml");
var titles = from element in doc.Descendants("book")
where (int)element.Element("price") > 20
select element.Element("title").Value;
d) Parallel LINQ (PLINQ)
Расширение LINQ to Objects для параллельного выполнения запросов на многоядерных процессорах.
var source = Enumerable.Range(1, 1000000);
var parallelQuery = source.AsParallel()
.Where(n => n % 2 == 0)
.ToArray(); // Выполняется параллельно
Ключевой принцип: Независимо от типа, LINQ использует отложенное выполнение (deferred execution). Запрос не выполняется до момента реальной итерации по результатам (например, в foreach, ToList(), Count()). Это позволяет строить и комбинировать запросы эффективно.
Ответ 18+ 🔞
А, LINQ, говоришь? Ну это ж, блядь, наше всё, как водка и балалайка в мире C#. Смотри, тут всё просто, но если не вникать — можно мозг сломать, как сухарик в борще.
Вот смотри, есть два главных способа эту штуку писать. Прям как водку пить — можно аккуратно из рюмки, а можно, прости господи, из горла.
Первый способ — для интеллигентов, которые SQL знают. Выглядит, будто с базой данных разговариваешь.
// Типа, выбери мне из всех продуктов дорогие электронные штуки и отсортируй по цене, чтоб самые жирные сверху были
var дорогиеШтуки = from штука in всеШтуки
where штука.Цена > 100 && штука.Категория == "Электроника"
orderby штука.Цена descending
select new { штука.Название, штука.Цена };
Выглядит чисто, читается легко, особенно если нужно таблицы между собой соединить (join). Но, сука, не всё через это можно сделать, иногда функционала не хватает.
Второй способ — для настоящих пацанов, которые любят цепочки. Тут всё через точки и стрелочки.
// Тот же запрос, но в стиле "не мешай мне, я строю"
var дорогиеШтуки = всеШтуки
.Where(ш => ш.Цена > 100 && ш.Категория == "Электроника")
.OrderByDescending(ш => ш.Цена)
.Select(ш => new { ш.Название, ш.Цена });
Этот способ, блядь, всеяден. Всё, что захочешь, можно сделать. Но если наворотить слишком длинную цепочку, можно самому в ней запутаться, как кот в клубке. А под капотом-то, ёпта, оба способа в одно и то же компилируются! Их даже мешать можно, но зачем усложнять?
А теперь, внимание, самое важное: куда этот LINQ применяется. Тут вариантов — как собак нерезаных.
-
LINQ to Objects. Это когда ты колупаешься в своих списках и массивах прямо в памяти. Основа основ.
List<int> циферки = new List<int> { 1, 2, 3, 4, 5 }; var чётные = циферки.Where(n => n % 2 == 0).ToList(); // Отфильтровал и всё тут -
LINQ to Entities (раньше LINQ to SQL). Вот это, блядь, магия. Ты пишешь запрос на C#, а Entity Framework берёт и превращает его в SQL, летящий прямиком в базу данных. Выглядит так же, а работает иначе.
using var db = new КонтекстБазы(); var пользователи = await db.Пользователи .Where(u => u.Активен) .OrderBy(u => u.Фамилия) .ToListAsync(); // Вжух — и SQL запрос готов! -
LINQ to XML. Для тех, кому приходится ковыряться в этих ваших XML-файлах. Делает процесс менее болезненным.
var doc = XDocument.Load("данные.xml"); var названия = from element in doc.Descendants("book") where (int)element.Element("price") > 20 select element.Element("title").Value; -
Parallel LINQ (PLINQ). А это для тех, у кого процессор ядер дохуя и он хочет их все загрузить. Кинул
.AsParallel()и поехали фильтровать миллион записей в несколько потоков.var source = Enumerable.Range(1, 1000000); var результат = source.AsParallel() .Where(n => n % 2 == 0) .ToArray(); // Работает быстрее, потому что параллельно!
И запомни, чувак, главный фокус всей этой кухни — отложенное выполнение. Это значит, что когда ты строил эту красивую цепочку из Where, Select и OrderBy, нихуя не происходило! Запрос выполнится только в тот момент, когда ты реально попросишь результат — в foreach, или через ToList(), или Count(). Это, с одной стороны, эффективно, а с другой — можно нечаянно десять раз к базе данных сходить, если невнимательный. Так что держи ухо востро.