Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C#

Lambda Expression trong C#: Cú pháp và ví dụ

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ạiCú phápVí dụ
Expression Lambda(args) => expressionx => x * x, (a,b) => a + b
Statement Lambda(args) => { statements; }x => { Console.WriteLine(x); return x*2; }
Async Lambdaasync (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, in parameter trong lambda.
  • return trong lambda chỉ return từ lambda, không return từ method bao quanh.
  • Không dùng goto, break, continue nhảy ra khỏi lambda block.
  • Biến trong lambda không hiển thấy ngoài lambda.