前幾節主要從語法與功能角度介紹 Lambda 表達式,大多數範例不用 Lambda 也能寫出來。本節將展示幾個具備實用價值的實例,讓你體會 Lambda 如何簡化程式碼結構。
假設有一個整數陣列,需以各元素為除數執行除法。若陣列包含 0,直接除法會拋出異常。傳統做法是在 foreach 迴圈內判斷:
int[] a = { 1, 2, 0 };
foreach (int n in a) {
if (n == 0) {
Console.WriteLine("陣列裡含有 0。");
return;
}
Console.WriteLine(100 / n);
}
// 輸出:100, 50, "陣列裡含有 0。"
這樣寫的缺點:計算開始後才發現 0,可能已輸出部分結果;若想在計算前檢查完畢,需額外加一個迴圈,顯得冗長。
Any 擴展方法引入 System.Linq 後,可用 Any 一行搞定預檢:
using System.Linq;
int[] a = { 1, 2, 0 };
if (a.Any(x => x == 0)) {
Console.WriteLine("陣列中含有 0");
return;
}
foreach (int n in a) Console.WriteLine(100 / n);
// 輸出:"陣列中含有 0"
Any 若集合中任一元素滿足條件即回傳 true。這樣在不犧牲可讀性下,以單一 if 取代雙重迴圈,程式碼更清晰。
若環境限制為 .NET Framework 2.0,可改用 Array.FindIndex:
if (Array.FindIndex(a, x => x == 0) >= 0) { ... }
這展示了 Lambda 對集合處理如同對單一值判斷般直觀:if (n == 0) → if (a.Any(x => x == 0))。
Lambda 語法靈活,尤其參數只有一時可省略括號,初學者易混淆。下列程式碼列舉主流變體:
delegate int NoArg();
delegate int OneArg(int onlyOne);
delegate int TwoArgs(int first, int second);
delegate void NoRetVal();
class Program {
static void Main() {
NoArg sample1 = () => 0;
OneArg sample2 = (x) => x * 2;
OneArg sample3 = (int x) => x * 2;
OneArg sample4 = x => x * 2; // 單參數可省略括號
TwoArgs sample5 = (x, y) => x * y;
TwoArgs sample6 = (int x, int y) => x * y;
OneArg sample7 = (x) => { return x * 2; }; // 陳述式主體
OneArg sample8 = (int x) => { return x * 2; };
NoRetVal sample9 = () => Console.WriteLine("Hello!");
}
}
() => 0:無參數時必須寫空括號。(x) => x * 2:有參數時以括號括起為基本寫法。(int x) => x * 2:可顯式指定參數型別。x => x * 2:僅當參數只有一個時,可省略括號。(x, y) => x * y:多參數以逗號分隔,括號不可省略。(int x, int y) => x * y:多參數亦可指定型別。(x) => { return x * 2; }:陳述式主體需用大括號並加 return。() => Console.WriteLine("Hello!"):無回傳值時直接呼叫 void 方法。掌握上述變體後,Lambda 表達式的大部分語法已涵蓋。但要完全理解其背後的型別推斷機制,以及 Action、Func 等委派在類別庫中的應用,仍有更深層內容待探討。下一章將深入型別推斷與委派類型的實務運用。