C# 定義六大比較運算子 (==, !=, <, >, <=, >=),但其在不同類型 (數值、布林、列舉、字串、委派、參考) 上的語意差異極大。深入理解這些細節,能避免微妙的 Bug 與效能陷阱。
| 運算子 | 名稱 | 回傳型別 |
|---|---|---|
== | 等於 | bool |
!= | 不等於 | bool |
< | 小於 | bool |
> | 大於 | bool |
<= | 小於或等於 | bool |
>= | 大於或等於 | bool |
double nan = double.NaN; nan == nan // false (NaN 不等於自己!) nan != nan // true (唯一「自己不等於自己」的值) nan < 0 // false nan > 0 // false nan <= 0 // false nan >= 0 // false // 關鍵推論:!(x == y) != (x != y) 當 NaN 參與時 // 正確檢查 NaN:double.IsNaN(x)
+0.0 == -0.0 // true (正負零相等) +0.0 > -0.0 // false double.PositiveInfinity > 1e308 // true double.NegativeInfinity < -1e308 // true // 無窮大運算 1.0 / 0.0 // +Infinity -1.0 / 0.0 // -Infinity 0.0 / 0.0 // NaN
-∞ < -MaxValue < ... < -MinValue < -0.0 == +0.0 < +MinValue < ... < +MaxValue < +∞ < NaN (無序)
// 隱含轉換:int → long → float → double 5 == 5.0 // true (int 轉 double) 5 == 5.0f // true (int 轉 float) long.MaxValue == double.MaxValue // false (精度遺失) // 危險:大整數轉 float 失去精度 long big = 9_000_000_000_000_000_000L; float f = big; // 精度遺失 big == f // false! (f 被四捨五入)
| 運算子 | 支援 | 語意 |
|---|---|---|
==, != | ✅ | 值相等比較 |
<, >, <=, >= | ❌ | 編譯錯誤 |
false == false // true true != false // true // true < false // CS0019: 無法套用運算子 // 關鍵:!= 等價於 ^ (XOR) bool a = true, b = false; a != b // true a ^ b // true (相同結果)
enum Priority { Low = 1, Medium = 2, High = 3 }
Priority p1 = Priority.Medium;
Priority p2 = Priority.High;
p1 < p2 // true (比較底層值 2 < 3)
p1 == p2 // false
p1 >= Priority.Low // true
// 底層機制:((U)p1) op ((U)p2) — 比較基底整數值
// 比較字元序列,非參考 "hello" == "hello" // true string s1 = "he" + "llo"; string s2 = "hello"; s1 == s2 // true (不同物件,同值) // 區分大小寫 "Hello" == "hello" // false // null 處理 null == null // true "text" == null // false
object.ReferenceEquals(s1, s2) // false (不同實例) object.ReferenceEquals(s1, "hello") // 可能 true (字串駐留)
// 忽略大小寫
string.Equals("HELLO", "hello", StringComparison.OrdinalIgnoreCase) // true
// 當前文化特定
"İ".Equals("i", StringComparison.CurrentCulture) // true (土耳其語 İ)
// 序數 (最快、預設 == 行為)
"HELLO".Equals("hello", StringComparison.Ordinal) // false
class Person { public string Name; }
var p1 = new Person { Name = "Alice" };
var p2 = new Person { Name = "Alice" };
var p3 = p1;
p1 == p2 // false (不同參考,除非多載 ==)
p1 == p3 // true (同參考)
// 多載 == 時建議同時多載 !=、Equals、GetHashCode
Action a1 = () => Console.WriteLine(1); Action a2 = () => Console.WriteLine(1); Action a3 = a1; a1 == a2 // false (不同實例,即使方法相同) a1 == a3 // true (同參考) Action multi = a1 + a2; multi == (a1 + a2) // true (同調用清單順序)
public readonly struct Temperature : IEquatable, IComparable { public double Celsius { get; } public static bool operator ==(Temperature left, Temperature right) => left.Celsius == right.Celsius; public static bool operator !=(Temperature left, Temperature right) => !(left == right); public static bool operator <(Temperature left, Temperature right) => left.Celsius < right.Celsius; public static bool operator >(Temperature left, Temperature right) => left.Celsius > right.Celsius; public static bool operator <=(Temperature left, Temperature right) => left.Celsius <= right.Celsius; public static bool operator >=(Temperature left, Temperature right) => left.Celsius >= right.Celsius; // 必須覆寫 public override bool Equals(object obj) => obj is Temperature t && this == t; public bool Equals(Temperature other) => this == other; public override int GetHashCode() => Celsius.GetHashCode(); }
Math.Abs(a - b) < epsilon精通各類型比較語意細節,是編寫正確、高效且可移植 C# 程式碼的關鍵基礎能力。