Hashtable、Dictionary<TKey, TValue> 等字典集合底層採用雜湊表演算法。鍵值對的儲存位置由 Key 的 GetHashCode() 決定;發生碰撞時再呼叫 Equals() 比對。若自訂類別作為 Key,必須正確覆寫 GetHashCode() 與 Equals(),否則會導致查找失敗、資料遺失或效能退化。
key.GetHashCode() 取得雜湊碼。key.Equals(existingKey) 判斷是否相同鍵。a.Equals(b) == true ⇒ a.GetHashCode() == b.GetHashCode()。Equals(object)、GetHashCode()、實作 IEquatable<T>、多載 ==/!= 運算子 形成完整相等邏輯。
public class EmployeeID : IEquatable
{
public string Id { get; }
public EmployeeID(string id) => Id = id ?? throw new ArgumentNullException(nameof(id));
public override int GetHashCode()
{
// 使用 StringComparer.OrdinalIgnoreCase 等標準雜湊演算法
return StringComparer.OrdinalIgnoreCase.GetHashCode(Id);
}
public override bool Equals(object obj) => Equals(obj as EmployeeID);
public bool Equals(EmployeeID other)
{
if (other is null) return false;
return StringComparer.OrdinalIgnoreCase.Equals(Id, other.Id);
}
public static bool operator ==(EmployeeID a, EmployeeID b)
=> ReferenceEquals(a, null) ? ReferenceEquals(b, null) : a.Equals(b);
public static bool operator !=(EmployeeID a, EmployeeID b) => !(a == b);
public override string ToString() => Id;
}
var dict = new Dictionary
{
[new EmployeeID("A0001")] = new EmployeeData("Johnny", 24, "Male"),
[new EmployeeID("A0002")] = new EmployeeData("Vicky", 20, "Female")
};
EmployeeID query = new EmployeeID("A0001");
if (dict.TryGetValue(query, out var emp))
Console.WriteLine($"{emp.Name}, {emp.Age}, {emp.Gender}");
Equals 未覆寫 GetHashCode → 繼承 object 預設雜湊碼(參考相等),導致邏輯相等但雜湊碼不同,查找失敗。GetHashCode 回傳常數(如 return 1;) → 所有物件落入同一桶,退化為 O(n) 線性搜尋。string、int、Guid 等內建型別作為 Key,已經過高度優化。readonly struct 或 sealed class 且所有相關欄位 readonly。Dictionary<TKey, TValue> 而非非泛型 Hashtable,避免裝箱拆箱。