JavaRush /Курси /C# SELF /Синтаксис лямбда-виразів ( =&...

Синтаксис лямбда-виразів ( =>)

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

1. Вступ

Можливо, ви цього ще не знаєте, але одне з улюблених питань на співбесідах — «Що ви знаєте про лямбда-вирази?». Чому про них питають? Бо це дуже зручний і «модний» прийом у C#, що дає змогу писати менше коду й робити його виразнішим. Якщо анонімні методи — це як писати листа від руки, то лямбда-вирази — як надсилати повідомлення у месенджері: швидко, компактно й інколи навіть зі смайликами (ну, майже).

Лямбда-вирази з’явилися у C# з версії 3.0, і відтоді вони повсюдні: у LINQ, обробниках подій, потоках, колекціях і навіть у бібліотеках штучного інтелекту для .NET.

Лямбда-вираз — це спосіб оголосити метод просто у тілі коду, «на місці», без імені, надкоротко й зрозуміло. Базовий синтаксис завжди виглядає так:

(параметри) => вираз_або_блок_коду

Цю «стрілочку» => називають лямбда-оператором або просто «стрілкою».

Невеличка аналогія

Згадайте, як ви записуєте рецепт: «Взяти яблуко, порізати його, покласти в миску».
У C# це було б:

(яблуко) => порізати(яблуко)

2. Перероблюємо анонімний метод на лямбду

Припустімо, у нас є делегат:

delegate int SquareDelegate(int x);

Анонімний метод виглядав би так:

SquareDelegate sq = delegate(int x) {
    return x * x;
};

А тепер те саме через лямбда-вираз:

SquareDelegate sq = (int x) => { return x * x; };

Але C# вміє виводити типи, тож можемо ще скоротити:

SquareDelegate sq = x => x * x;

Вражаюча компактність!

Порівняння зі «звичайним» методом і анонімною функцією

Спосіб Оголошення Де можна використовувати Мінуси
Іменований метод У класі Скрізь Потрібне імʼя, більше коду
Анонімний метод У коді Лише з делегатами Громіздкіший синтаксис
Лямбда-вираз У коді Скрізь із делегатами Іноді тип неочевидний

3. Синтаксис лямбда-виразу: варіації

Параметри

Без параметрів:

Action hello = () => Console.WriteLine("Привіт, світ!");

Один параметр (можна опустити дужки):

Func<int, int> inc = x => x + 1;

Кілька параметрів (потрібні дужки):

Func<int, int, int> sum = (a, b) => a + b;

Тіло лямбди

Один вираз — без фігурних дужок і return:

x => x * x

Блок коду — фігурні дужки, потрібен return:

(x, y) =>
{
    int z = x + y;
    return z * z;
}

Типи параметрів

Найчастіше тип вказувати не потрібно — компілятор здогадається. Але якщо хочете — будь ласка:

(x, y) => x + y      // Компілятор сам виводить типи.
(int x, int y) => x + y  // Можна явно.

4. Нюанси та більш реальні приклади

Використання з колекціями

Пам’ятаєте наш навчальний міні‑застосунок (наприклад, список користувачів)? Припустімо, у нас є масив чисел:

int[] numbers = { 1, 2, 3, 4, 5 };

Треба обрати лише парні числа:

var evenNumbers = numbers.Where(n => n % 2 == 0);

Тут Where — метод-розширення LINQ, а умова — наш лямбда-фільтр.

Передача в метод

Припустімо, у нас є метод-делегат:

public delegate bool Filter(int number);

public static int[] FilterNumbers(int[] data, Filter predicate)
{
    var result = new List<int>();
    foreach (var n in data)
        if (predicate(n))
            result.Add(n);
    return result.ToArray();
}

Тепер передаємо лямбда-вираз:

int[] evens = FilterNumbers(numbers, n => n % 2 == 0);

Лямбда як обробник подій

button.Click += (sender, args) => Console.WriteLine("Кнопку натиснуто!");

5. Лямбда-вирази і стандартні узагальнені делегати

Лямбди важко уявити без Func<>, Action<> і Predicate<>. Це спеціальні типи делегатів:

  • Action — нічого не повертає.
  • Func — повертає значення.
  • Predicate — повертає bool, зазвичай для фільтрації.

Приклад з Action:

Action<string> log = message => Console.WriteLine(message);

log("Це повідомлення через лямбду!");

Приклад з Func:

Func<int, int, int> multiply = (a, b) => a * b;
int product = multiply(3, 5); // 15

Приклад з Predicate:

Predicate<int> isNegative = n => n < 0;

bool test = isNegative(-7); // true

6. Лямбди з кількома виразами: коли потрібен блок

Якщо лямбда має виконувати кілька операцій, використовуйте фігурні дужки й явний return:

Func<int, int, string> describeSum = (a, b) =>
{
    int sum = a + b;
    return $"Сума: {sum}";
};

Без return компілятор обуриться (але до ладу не пояснить чому — просто повідомить, що «не всі шляхи повертають значення»).

7. Повернення void: Action

Коли лямбда нічого не повертає, використовуйте Action:

Action greet = () => Console.WriteLine("Посміхайтеся — код компілюється!");

Лямбда може містити скільки завгодно інструкцій:

Action<int> printSquare = x =>
{
    int sq = x * x;
    Console.WriteLine($"Квадрат числа {x} дорівнює {sq}");
};

8. Обмеження та типові помилки

Іноді хочеться написати лямбду дуже довільно, але компілятор не завжди з цим погоджується.

Не можна оголошувати змінну з тим самим імʼям, що й захоплена ззовні.

Слідкуйте за типами: якщо сигнатура делегата й лямбди не збігається, буде помилка.

Повернення значення обов’язкове, якщо делегат його вимагає.

У складних лямбдах не забувайте про фігурні дужки. Один вираз — без дужок і return. Кілька інструкцій — дужки й return.

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