邏輯運算式結合關係運算與布林邏輯,構成程式決策的核心。C# 的 && (條件 AND) 與 || (條件 OR) 採用短路求值,不僅影響效能,更關係執行正確性與副作用控制。
| 運算子 | 短路條件 | 行為 |
|---|---|---|
a && b | a == false | 直接回傳 false,不評估 b |
a || b | a == true | 直接回傳 true,不評估 b |
關鍵含意:b 可能包含副作用(方法呼叫、屬性存取、遞增運算),短路會導致其完全不執行。
// 安全:obj 為 null 時,不執行 obj.Method()
if (obj != null && obj.IsValid()) { ... }
// 危險:使用 & 會評估右邊,拋出例外
if (obj != null & obj.IsValid()) { ... } // 錯誤!
// 快速檢查先行,昂貴運算只在必要時執行
if (cache.Contains(key) || ComputeExpensiveValue(key)) { ... }
// 反例:總是執行昂貴運算
if (ComputeExpensiveValue(key) || cache.Contains(key)) { ... }
int x = 0; bool result = false || (x++ > 0); // result = false, x = 1 (右邊執行了) result = true || (x++ > 0); // result = true, x = 1 (右邊被短路,x 不遞增!)
bool IsLeapYear(int year)
{
// 400 整除 || (4 整除 && 非 100 整除)
return (year % 400 == 0) || ((year % 4 == 0) && (year % 100 != 0));
}
// 短路優化版:優先檢查最常見情況
bool IsLeapYearOptimized(int year)
{
if (year % 4 != 0) return false; // 75% 情況快速排除
if (year % 100 == 0) return year % 400 == 0;
return true;
}
優先級 (高→低):! > && > || 結合性:左結合
隱含括號範例:
a || b && c // a || (b && c) !a && b || c // ((!a) && b) || c a && b || c && d // (a && b) || (c && d)
| 特性 | &, | | &&, || |
|---|---|---|
| 短路求值 | 否 (總評估兩邊) | 是 |
| 適用類型 | bool、整數 (位元運算) | 僅 bool |
| 可多載 | 是 | 否 (但可多載 true/false 運算子) |
| 用途 | 位元遮罩、旗標、需雙邊副作用 | 一般布林邏輯、防禦性檢查 |
// 兩個副作用都必須執行
if (ValidateInput() | SaveToDatabase()) { ... }
// 位元旗標操作
[Flags] enum Flags { A = 1, B = 2, C = 4 }
var f = Flags.A | Flags.B; // 合併
bool hasA = (f & Flags.A) != 0; // 檢測
&&/|| — 短路符合直覺、效能更好、防禦性更強&/|public struct Optional{ public bool HasValue { get; } public T Value { get; } // 必須同時定義 true/false 運算子才能支援 &&/|| public static bool operator true(Optional opt) => opt.HasValue; public static bool operator false(Optional opt) => !opt.HasValue; public static Optional operator &(Optional a, Optional b) => a.HasValue ? b : a; // 短路語意:a 無值則直接回傳 a public static Optional operator |(Optional a, Optional b) => a.HasValue ? a : b; }
深入理解短路求值語意,能編寫更健壯、高效且符合直覺的條件邏輯,是 C# 開發者的核心功力之一。