Что такое лямбда выражения в С#
Лямбда-выражения в C# — это краткая форма объявления анонимных методов (методов без имени), которые можно использовать для определения делегатов или выражений LINQ. Лямбда-выражения были введены в C# 3.0 и играют ключевую роль в функциональном стиле программирования внутри языка.
📌 Общий синтаксис
(parameters) => expression
или для блока кода:
(parameters) => { statements }
📌 Пример простого лямбда-выражения
Func<int, int> square = x => x \* x;
Console.WriteLine(square(5)); // 25
Здесь:
-
Func<int, int> — делегат, который принимает int и возвращает int.
-
x => x * x — лямбда-выражение, которое принимает параметр x и возвращает x * x.
📌 Использование с делегатами
Лямбда-выражения позволяют создать анонимные методы, которые легко передаются как параметры:
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
var evens = numbers.Where(n => n % 2 == 0).ToList(); // \[2, 4\]
В данном примере n => n % 2 == 0 — это предикат, переданный в метод Where.
📌 Использование с Action, Func и Predicate
- Action — ничего не возвращает:
Action<string> greet = name => Console.WriteLine($"Hello, {name}");
greet("Alice");
- Func<T, TResult> — возвращает значение:
Func<int, int> doubleIt = n => n \* 2;
Console.WriteLine(doubleIt(6)); // 12
- Predicate<T> — возвращает bool:
Predicate<int> isPositive = n => n > 0;
Console.WriteLine(isPositive(-5)); // false
📌 Множественные параметры
Func<int, int, int> add = (a, b) => a + b;
Console.WriteLine(add(3, 7)); // 10
📌 Блочные лямбда-выражения
Если тело выражения содержит несколько строк, используются фигурные скобки:
Func<int, int, int> multiplyAndAdd = (a, b) =>
{
int product = a \* b;
return product + 10;
};
Console.WriteLine(multiplyAndAdd(2, 3)); // 16
📌 Захват переменных из внешнего контекста (closure)
Лямбда-выражения могут использовать переменные из окружающей области видимости:
int factor = 10;
Func<int, int> multiply = x => x \* factor;
Console.WriteLine(multiply(5)); // 50
Если factor изменится — изменится и результат:
factor = 2;
Console.WriteLine(multiply(5)); // 10
📌 Лямбда и LINQ
Лямбда-выражения активно применяются в LINQ-запросах:
var numbers = new List<int> { 1, 2, 3, 4, 5 };
var squared = numbers.Select(x => x \* x).ToList(); // \[1, 4, 9, 16, 25\]
📌 Лямбда-выражения и Expression Trees
Когда используется Expression<Func
Expression<Func<int, bool>> expr = x => x > 10;
Такое дерево может быть разобрано, интерпретировано или преобразовано, что особенно полезно, например, в Entity Framework при формировании SQL-запросов.
📌 Сравнение с анонимными методами
До появления лямбд существовали анонимные методы:
Func<int, int> square = delegate (int x) {
return x \* x;
};
Лямбды — это более короткий и читаемый способ записи того же самого, к тому же они могут быть как выражением, так и блоком кода.
📌 Типизация
Тип параметров в лямбда-выражениях обычно выводится компилятором:
numbers.ForEach(n => Console.WriteLine(n)); // Тип n — int
Можно явно указать тип, но это делается редко:
numbers.ForEach((int n) => Console.WriteLine(n));
📌 Ограничения
-
Нельзя использовать goto, break, continue за пределами лямбда-тела.
-
Внутри лямбды нельзя использовать ref или out параметры напрямую.
-
Лямбда не может иметь атрибутов (в отличие от обычного метода).
📌 Примеры сложного применения
Фильтрация коллекции по нескольким условиям:
var filtered = items.Where(item =>
item.IsActive &&
item.Quantity > 0 &&
item.Name.StartsWith("A"));
Сортировка по нескольким полям:
var sorted = users.OrderBy(u => u.LastName).ThenBy(u => u.FirstName);
📌 Лямбды внутри событий
button.Click += (sender, args) => {
Console.WriteLine("Кнопка нажата!");
};
📌 Передача лямбд как параметров
void Process(Func<int, int> operation)
{
Console.WriteLine(operation(10));
}
Process(x => x + 5); // 15
📌 Лямбда внутри методов
Лямбды часто используются для написания компактного и читабельного кода без необходимости создавать отдельные методы. Это упрощает разработку, особенно при работе с LINQ, событиями, обработкой коллекций и функциональными интерфейсами.