Lambda Expression คือ Anonymous Function แบบกระชับ (Concise Syntax) ใช้สร้าง Delegate หรือ Expression Tree ได้ มีรูปแบบ:
(input-parameters) => expression // Expression Lambda
(input-parameters) => { statements; } // Statement Lambda
รูปแบบต่างๆ
1. Expression Lambda (Single Expression - Implicit Return)
// x => x * x
Func<int, int> square = x => x * x;
Console.WriteLine(square(5)); // 25
// Multiple Parameters
Func<int, int, int> add = (a, b) => a + b;
Console.WriteLine(add(3, 4)); // 7
// No Parameters
Action sayHello = () => Console.WriteLine("Hello!");
sayHello();
// Explicit Types
Func<int, int, bool> testEq = (int x, int y) => x == y;
2. Statement Lambda (Block Body - ต้องมี Return Statement)
Func<int, int, int> max = (a, b) =>
{
if (a > b) return a;
return b;
};
// Void Return (Action)
Action<string> log = msg =>
{
var timestamp = DateTime.Now.ToString("HH:mm:ss");
Console.WriteLine($"[{timestamp}] {msg}");
};
log("Application started");
3. Lambda กับ Delegate Types
| Delegate | Signature | ใช้เมื่อ |
|---|---|---|
Action |
void () | ไม่มี Parameter, ไม่ Return |
Action<T> |
void (T) | 1 Param, ไม่ Return |
Func<TResult> |
TResult () | ไม่มี Param, Return TResult |
Func<T, TResult> |
TResult (T) | 1 Param, Return TResult |
Func<T1, T2, TResult> |
TResult (T1, T2) | 2 Params, Return TResult |
| สูงสุด | Func<T1..T16, TResult> | 16 Params |
ตัวอย่างใช้งานจริง
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 doubled = numbers.Select(n => n * 2); // 2,4,6...
var sum = numbers.Where(n => n > 5).Sum(); // 40
// Complex
var grouped = numbers
.GroupBy(n => n % 2 == 0 ? "Even" : "Odd")
.Select(g => new { Type = g.Key, Count = g.Count(), Sum = g.Sum() });
Event Handlers
button.Click += (sender, e) => MessageBox.Show("Clicked!");
timer.Elapsed += (s, e) => Console.WriteLine($"Tick: {e.SignalTime}");
Thread/Task
Task.Run(() => DoBackgroundWork());
new Thread(() => ProcessQueue()).Start();
Tuple Lambda (C# 7+)
// Input Tuple
Func<(int X, int Y), double> distance = p => Math.Sqrt(p.X * p.X + p.Y * p.Y);
// Output Tuple
Func powers = x => (x * x, x * x * x);
var result = powers(3); // (9, 27)
Variable Capture (Closures)
int factor = 2;
Func multiplier = x => x * factor; // Capture 'factor'
factor = 10;
Console.WriteLine(multiplier(5)); // 50 (ใช้ค่าใหม่!)
// ⚠️ Loop Variable Capture Pitfall
var funcs = new List>();
for (int i = 0; i < 3; i++)
{
// ❌ ทุก Func จะ Capture ตัวแปร i เดียวกัน -> ทั้งหมดคืน 3
funcs.Add(() => i);
}
// ✅ Fix: Copy to Local Variable
for (int i = 0; i < 3; i++)
{
int captured = i; // Local Copy
funcs.Add(() => captured); // คืน 0, 1, 2
}
ข้อจำกัด
- ไม่สามารถ Capture
ref,out,inParameters ได้ returnใน Lambda ออกจาก Lambda เท่านั้น (ไม่ใช่ Enclosing Method)- ไม่มี
goto,break,continueข้าม Lambda Boundary - ไม่สามารถใช้
awaitใน Expression Lambda (ต้องเป็น Statement Lambda)
Expression Trees
Lambda กับ Expression<Func<T>> จะถูก Compile เป็น Expression Tree (Data Structure) ไม่ใช่ IL Code ใช้ใน LINQ to SQL, Entity Framework, Dynamic Queries
Expression> expr = x => x > 5; // Data Structure
Func compiled = expr.Compile(); // Compile to Delegate
สรุป
Lambda Expression = Syntactic Sugar สำหรับ Anonymous Methods ทำให้โค้ดสั้น อ่านง่าย รองรับ Functional Style เป็นพื้นฐานของ LINQ, Async, Event Handling, DI