C# 允許多載運算子,但規則比 C++ 嚴格:必須為 static、至少一個參數為宣告類別型別、比較運算子必須成對實作、且必須覆寫 Equals 與 GetHashCode。本文詳細說明規則與完整範例。
| 類別 | 運算子 | 成對要求 |
|---|---|---|
| 比較 | ==, != | 是 |
| 關係 | <, >, <=, >= | 是 |
| 邏輯 | true, false | 是 |
| 算術 | +, -, *, /, % | 否 |
| 一元 | ++, --, !, ~ | 否 |
此外,多載 == 時編譯器會強制要求覆寫 Equals(object) 與 GetHashCode(),確保集合行為一致。
public class Namer
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Namer() : this(null, null) { }
public Namer(string fn, string ln) { FirstName = fn; LastName = ln; }
// 1. true/false 運算子:判斷姓名是否完整
public static bool operator true(Namer n)
=> n?.FirstName != null && n.LastName != null;
public static bool operator false(Namer n)
=> n?.FirstName == null || n.LastName == null;
// 2. 相等/不相等
public static bool operator ==(Namer n1, Namer n2)
{
if (ReferenceEquals(n1, n2)) return true;
if (n1 is null || n2 is null) return false;
return n1.FirstName == n2.FirstName && n1.LastName == n2.LastName;
}
public static bool operator !=(Namer n1, Namer n2)
=> !(n1 == n2);
// 3. 大小比較 (依姓氏再名字字典序)
public static bool operator >(Namer n1, Namer n2)
{
if (n1 is null || n2 is null) return false;
int cmp = string.Compare(n1.LastName, n2.LastName, StringComparison.Ordinal);
return cmp > 0 || (cmp == 0 && string.Compare(n1.FirstName, n2.FirstName, StringComparison.Ordinal) > 0);
}
public static bool operator <(Namer n1, Namer n2)
=> n2 > n1;
// 4. 必須覆寫
public override bool Equals(object obj)
=> obj is Namer other && this == other;
public override int GetHashCode()
=> (FirstName, LastName).GetHashCode();
public override string ToString()
=> $"姓:{FirstName} 名:{LastName}";
}
static void Main()
{
var n1 = new Namer("Li", "Zanhong");
var n2 = new Namer("Ahang", "Aan");
Console.WriteLine(n1 == n2 ? "同名" : "不同名"); // 不同名
Console.WriteLine(n1 != n2 ? "不等成立" : "相等成立"); // 不等成立
Console.WriteLine(n1 > n2 ? $"{n1} > {n2}" : n1 < n2 ? $"{n1} < {n2}" : "無法比較");
// 輸出: 姓:Li 名:Zanhong > 姓:Ahang 名:Aan
// 測試 true/false 運算子 (用於 if 條件)
Namer incomplete = new Namer("OnlyFirst", null);
if (incomplete) Console.WriteLine("完整"); else Console.WriteLine("不完整"); // 不完整
}
== 不寫 != → 編譯錯誤 CS0216。Dictionary、HashSet 行為異常。GetHashCode 應基於參與比較的欄位計算。== 實作中先檢查 ReferenceEquals 與 null,避免無限遞迴。掌握 C# 運算子多載的嚴格規則,能讓自訂型別像內建型別一樣自然參與運算與比較,提升程式碼可讀性與型別安全性。