首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

Effective C# 原則 9:掌握四種相等比較的關係與正確覆寫策略

     編輯:關於C#

C# 提供四種相等比較機制,定義型別時必須釐清其語意:

  • Object.ReferenceEquals(a, b) — 參考相等(同一物件實例)。
  • Object.Equals(a, b) — 靜態相等,委派給 a.Equals(b)。
  • a.Equals(b) — 實例相等,可覆寫定義值語意。
  • a == b — 運算子相等,可多載(實值型別建議多載)。

永不覆寫的兩個方法

  • ReferenceEquals:永遠比較物件 ID,實值型別裝箱後永回傳 false,語意固定。
  • Object.Equals(static):標準實作已正確處理 null、參考相等、委派給左運算元實例方法。覆寫反而破壞多型行為。

數學相等性質(必須滿足)

  • 自反性:a == a 恆真。
  • 對稱性:a == b → b == a。
  • 傳遞性:a == b ∧ b == c → a == c。

何時覆寫 Instance Equals()?

  • 實值型別:必須覆寫。ValueType.Equals() 使用反射逐欄位比較,效能極差。
  • 參考型別:需值語意時覆寫。如 string、DataRowView 比較內容而非參考。

標準 Instance Equals() 實作模式

public override bool Equals(object right)
{
    if (right == null) return false;
    if (ReferenceEquals(this, right)) return true;
    if (GetType() != right.GetType()) return false; // 嚴格型別檢查,保證對稱性
    return CompareMembers(this, (MyType)right);
}

繼承體系中的對稱性陷阱

基類用 as Base、衍生類用 as Derived 會導致:

Base b = new Base();
Derived d = new Derived();
b.Equals(d) → 可能 true(d 隱式轉 Base)
d.Equals(b) → 永遠 false(b 無法轉 Derived)
// 破壞對稱性!

解法:GetType() != right.GetType() 嚴格檢查,或不支援跨型別相等比較。

基類 Equalls() 呼叫鏈

  • 衍生類 Equals 應呼叫 base.Equals(right) 比較基類部分。
  • 基類若未覆寫,應呼叫 base.Equals(right)(即 Object.Equals),而非直接比較參考。

運算子 == 多載策略

  • 實值型別:必須多載。預設參考比較錯誤且低效(裝箱)。避免裝箱:參數型別宣告為實值型別。
  • 參考型別:一般不多載。保持參考語意,避免與 Equals() 行為不一致造成困擾。

決策速查表

型別Instance Equals()Operator ==
實值型別必須覆寫(效能)必須多載(正確性+效能)
參考型別(值語意)覆寫不建議
參考型別(參考語意)不覆寫不多載

覆寫 Equals() 時必須同步覆寫 GetHashCode()(原則 10)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved