Lambda Expression là anonymous function ngắn gọn, dùng để tạo delegate hoặc expression tree. Cú pháp: (parameters) => expression hoặc (parameters) => { statements; }.
Các dạng Lambda
| Loại | Cú pháp | Ví dụ |
|---|---|---|
| Expression Lambda | (args) => expression | x => x * x, (a,b) => a + b |
| Statement Lambda | (args) => { statements; } | x => { Console.WriteLine(x); return x*2; } |
| Async Lambda | async (args) => { await ...; } | async () => await FetchAsync() |
| Discard Parameter | _ => expr hoặc (_, _) => expr | _ => DoWork() |
Delegate Types phổ biến
Func<TResult>: 0 tham số, trả về TResult.Func<T, TResult>: 1 tham số T, trả về TResult.Func<T1, T2, TResult>: 2 tham số, trả về TResult (tối đa 16 tham số).Action: 0 tham số, void.Action<T>: 1 tham số, void.Action<T1, T2>: 2 tham số, void.
Ví dụ cơ bản
// Func - nhận int, trả int
Func square = x => x * x;
Console.WriteLine(square(5)); // 25
// Func
Func equal = (a, b) => a == b;
Console.WriteLine(equal(3, 3)); // True
// Action - nhận string, void
Action print = s => Console.WriteLine($"Log: {s}");
print("Hello"); // Log: Hello
// Statement lambda
Func factorial = n => {
int result = 1;
for (int i = 2; i <= n; i++) result *= i;
return result;
};
Console.WriteLine(factorial(5)); // 120
Lambda với LINQ
var numbers = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var evens = numbers.Where(n => n % 2 == 0); // 2,4,6,8,10
var squares = numbers.Select(n => n * n); // 1,4,9,16,25...
var sum = numbers.Where(n => n > 5).Sum(); // 6+7+8+9+10 = 40
var grouped = numbers.GroupBy(n => n % 2); // Group by even/odd
Lambda và Variable Capture (Closure)
int factor = 10;
Func multiply = x => x * factor; // Capture 'factor'
factor = 20; // Thay đổi biến outer
Console.WriteLine(multiply(5)); // 100 (dùng giá trị mới = 20)
// CẨN THẬN: Closure trong loop (classic pitfall)
var funcs = new List>();
for (int i = 0; i < 3; i++)
{
funcs.Add(() => i); // Capture BIẾN i, không phải GIÁ TRỊ i
}
foreach (var f in funcs) Console.WriteLine(f()); // 3, 3, 3 (không phải 0,1,2)
// Fix: copy to local variable
for (int i = 0; i < 3; i++)
{
int captured = i;
funcs.Add(() => captured);
}
// Output: 0, 1, 2
Expression Trees (Expression<TDelegate>)
using System.Linq.Expressions;
// Expression tree - có thể inspect, compile, serialize
Expression> expr = x => x * x + 2 * x + 1;
// Compile to delegate at runtime
Func compiled = expr.Compile();
Console.WriteLine(compiled(3)); // 16
// Inspect structure
Console.WriteLine(expr.Body.NodeType); // Add
Console.WriteLine(expr.Parameters[0].Name); // x
Quy tắc quan trọng
- Không dùng
ref,out,inparameter trong lambda. returntrong lambda chỉ return từ lambda, không return từ method bao quanh.- Không dùng
goto,break,continuenhảy ra khỏi lambda block. - Biến trong lambda không hiển thấy ngoài lambda.