JavaRush /Курси /C# SELF /Синтаксис LINQ: Method Syntax vs Query Syntax

Синтаксис LINQ: Method Syntax vs Query Syntax

C# SELF
Рівень 31 , Лекція 1
Відкрита

1. Вступ

У світі LINQ є дві основні «школи» написання запитів, два стилі, які на перший погляд можуть здатися зовсім різними. Це Query Syntax (синтаксис запитів) і Method Syntax (синтаксис методів). І якщо ви колись думали, що програмування — це суто логіка, то сьогодні ми додамо трохи мистецтва, адже вибір синтаксису часто схожий на вибір між пензлем і олівцем: обидва інструменти малюють, але один краще передає колір, а інший — контур.

Навіщо два синтаксичні стилі? Гарне питання! Уявіть, що ви хочете замовити каву. Можете сказати: «Можна, будь ласка, чашку еспресо з молоком і однією ложкою цукру?». А можете написати на папірці: «Еспресо. Молоко. 1 цукор». Обидва варіанти зрозумілі, але один — більш розмовний, інший — коротший.

Так само і з LINQ. Один синтаксис створили, щоб бути максимально схожим на мову баз даних SQL, а інший — щоб бути ближчим до C# і гнучкішим. Врешті‑решт компілятор C# перетворює обидва стилі на одне й те саме: у виклики методів. Тому вибір часто зводиться до читабельності й особистих уподобань.

Розгляньмо обидва.

2. Method Syntax

Це варіант, коли ви викликаєте LINQ‑методи‑розширення один за одним через крапку. Такий підхід особливо популярний серед .NET‑розробників, адже легко додавати нові операції, результат завжди IEnumerable<T>, і писати зручно прямо в коді.

Приклад: відфільтрувати й відсортувати товари


var filteredProducts = products
    .Where(p => p.Price < 1000)          // Фільтруємо за ціною
    .OrderBy(p => p.Name)                // Сортуємо за іменем
    .ToList();                           // Перетворюємо у список List<Product>

Where, OrderBy і ToList — це LINQ‑методи‑розширення, кожен повертає новий набір даних, який можна далі обробляти.

Схема

Послідовність викликів у Method Syntax

Переваги Method Syntax

  • Дуже гнучкий підхід: легко будувати складні ланцюжки з багатьох операцій.
  • Усі методи — звичайні C#‑методи, IDE допомагає автодоповненням.
  • Дозволяє робити майже все, що є в LINQ (і навіть більше).

Ще один приклад: вибір імен усіх користувачів віком від 18 років

Припустімо, що маємо клас User:


public class User
{
    public string Name { get; set; }
    public int Age { get; set; }
}

Тепер виберімо імена дорослих користувачів:


List<User> users = ... // оголошено десь

var adultNames = users
    .Where(u => u.Age >= 18)
    .Select(u => u.Name)
    .ToList();

3. Query Syntax (SQL‑подібний синтаксис)

Цей синтаксис спеціально створили, щоб C#‑розробники почувалися, як удома, якщо раніше працювали з SQL. Він схожий на запити до баз даних і починається з ключового слова from.

Приклад: той самий фільтр і сортування


var filteredProducts = 
    from p in products
    where p.Price < 1000
    orderby p.Name
    select p;

Тут усе читається як класичний запит: «з колекції products взяти p, де p.Price < 1000, відсортувати за p.Name, вибрати p».

Схема

Етапи запиту в Query Syntax

Переваги Query Syntax

  • Схожий на SQL, тож зрозуміліший для тих, хто вже працював із базами даних.
  • Більш читабельний для довгих запитів із кількома умовами, групуваннями, об’єднаннями (join).

Ще приклад: вибір імен дорослих користувачів


var adultNames = 
    from u in users
    where u.Age >= 18
    select u.Name;

Зверніть увагу: тут одразу після select можна вибрати не весь об’єкт, а конкретне поле — наприклад, тільки імʼя.

4. Порівняння: Method Syntax vs Query Syntax

Method Syntax Query Syntax
Синтаксис
users.Where(...).Select(...)
from u in users where ... select ...
Схожий на Звичайні методи/ланцюжки SQL
Де застосовується Завжди, для будь‑яких операцій Не всі операції доступні (наприклад,
Sum
,
Count
лише в Method Syntax)
Читабельність Добре для ланцюжків Зручніше для групувань, об’єднань
Що повертає Зазвичай
IEnumerable<T>
Зазвичай
IEnumerable<T>
, але інколи потрібен
.ToList()
для списку

Цікавий факт із реального життя

Більшість прикладів в офіційній документації Microsoft щодо LINQ наводять одразу в двох стилях. Проте у промисловому коді дедалі частіше трапляється Method Syntax — він зручніший для інтеграції з методами‑розширеннями (Where, Select, OrderBy тощо).

Міксувати чи не міксувати? Який стиль обрати

Можна спокійно поєднувати обидва стилі в одному проєкті (і навіть в одному запиті — але це виглядає дивно). Головне — не перетворювати код на мішанину. Зазвичай обирають один стиль на весь модуль чи проєкт, щоб код було простіше читати.

Method Syntax чудово підходить для послідовних перетворень і використання всіх LINQ‑методів, наявних лише у вигляді методів (Sum, Count, Any та деякі інші).

Query Syntax дуже зручний для завдань із join, group by чи складними багаторівневими умовами — там він виграє за читабельністю.

5. Перетворення між стилями: одне й те саме, але по‑різному

У C# будь‑який SQL‑подібний запит (Query Syntax) компілюється в ланцюжок викликів методів (Method Syntax). Тобто що б ви не написали, C# усе одно зведе це до методів‑розширень під час компіляції.

Приклад 1 — фільтрація:

Query Syntax:


var adults = from u in users
             where u.Age >= 18
             select u;

Method Syntax (еквівалент):


var adults = users.Where(u => u.Age >= 18);

Приклад 2 — вибірка полів (Select):

Query Syntax:


var names = from u in users
            select u.Name;

Method Syntax:


var names = users.Select(u => u.Name);

7. Групування та об’єднання (join, group by)

Створення нових об’єктів

Додаймо до нашого навчального застосунку можливість виводити список користувачів, згрупованих за віком. Тут різниця в синтаксисі стає особливо помітною.

Query Syntax (групування):


var usersByAge = 
    from u in users
    group u by u.Age into ageGroup
    select new { Age = ageGroup.Key, Users = ageGroup.ToList() };

Ми групуємо користувачів за віком (group u by u.Age). Після into з’являється змінна ageGroup — це вже сама група.

Method Syntax (еквівалент):


var usersByAge = users
    .GroupBy(u => u.Age)
    .Select(ageGroup => new { Age = ageGroup.Key, Users = ageGroup.ToList() });

Ще складніше: об’єднання (join)

Припустімо, що маємо список замовлень (orders) і список користувачів (users). Хочемо отримати імена користувачів і суму їхніх замовлень.

Query Syntax:


var userOrders =
    from user in users
    join order in orders on user.Id equals order.UserId
    select new { user.Name, order.Amount };

Method Syntax:


var userOrders = users.Join(
    orders,
    user => user.Id,
    order => order.UserId,
    (user, order) => new { user.Name, order.Amount }
);

8. Часті помилки, підводні камені та поради

Одна з найчастіших помилок: якщо ви не додали .ToList(), результат — не список, а «відкладений запит» (lazy query), який виконається лише під час першої ітерації. Це зручно, але може призвести до неочікуваних результатів, якщо вихідна колекція зміниться після його формування. Детальніше про «відкладене виконання» поговоримо окремо (після знайомства з LINQ‑методами).

Часто плутають: не всі LINQ‑методи можна використовувати в Query Syntax. Наприклад, не можна просто так написати select sum(u.Age) — потрібно перейти до Method Syntax (users.Sum(u => u.Age)).

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ