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.

2
Задача
C# SELF, 49 уровень, 1 лекция
Недоступна
Лямбда-выражение с несколькими параметрами для сложения чисел
Лямбда-выражение с несколькими параметрами для сложения чисел
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ