Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

Lambda Expression ใน C# คืออะไร

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, in Parameters ได้
  • 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