程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> Effective C#原則9:明白幾個相等運算之間的關系(2)

Effective C#原則9:明白幾個相等運算之間的關系(2)

編輯:關於C語言
個示例代碼展示的兩個方法是我還沒有討論 的:操作符==()和實例的Equals()方法。我會詳細的解釋這兩個,但我還沒有准 備結束對靜態的Equals()的討論。現在,我希望你明白,靜態的Equals()是使用 左邊參數實例的Equals()方法來斷定兩個對象是否相等。

與 ReferenceEquals()一樣,你或許從來不會重新定義靜態的Object.Equals()方法 ,因為它已經確實的完成了它應該完成的事:在你不知道兩個對象的確切類型時 斷定它們是否是一樣的。因為靜態的Equals()方法把比較委托給左邊參數實例的 Equals(),它就是用這一原則來處理另一個類型的。

現在你應該明白為 什麼你從來不必重新定義靜態的ReferenceEquals()以及靜態的Equals()方法了 吧。現在來討論你須要重載的方法。但首先,讓我們先來討論一下這樣的一個與 相等相關的數學性質。你必須確保你重新定義的方法的實現要與其它程序員所期 望的實現是一致的。這就是說你必須確保這樣的一個數學相等性質:相等的自反 性,對稱性和傳遞性。自反性就是說一個對象是等於它自己的,不管對於什麼類 型,a==a總應該返回true;對稱就是說,如果有a==b為真,那麼b==a也必須為真 ;傳遞性就是說,如果a==b為真,且b==c也為真,那麼a==c也必須為真,這就是 傳遞性。

現在是時候來討論實例的Object.Equals()函數了,包括你應該 在什麼時候來重載它。當默認的行為與你的類型不一致時,你應該創建你自己的 實例版本。Object.Equals()方法使用對象的ID來斷定兩個變量是否相等。這個 默認的Object.Equals()函數的行為與Object.ReferenceEquals()確實是一樣的 。但是請注意,值類型是不一樣的。System.ValueType並沒有重載 Object.Equals(),記住,System.ValueType是所有你所創建的值類型(使用關鍵 字struct創建)的基類。兩個值類型的變量相等,如果它們的類型和內容都是一 樣的。ValueType.Equals()實現了這一行為。不幸的是,ValueType.Equals()並 不是一個高效的實現。ValueType.Equals()是所有值類型的基類(譯注:這裡是 說這個方法在基類上進行比較)。為了提供正確的行為,它必須比較派生類的所 有成員變量,而且是在不知道派生類的類型的情況下。在C#裡,這就意味著要使 用反射。正如你將會在原則44裡看到的,對反射而言它們有太多的不利之處,特 別是在以性能為目標的時候。

相等是在應用中經常調用的基礎結構之一 ,因此性能應該是值得考慮的目標。在大多數情況下,你可以為你的任何值類型 重載一個快得多的Equals()。簡單的推薦一下:在你創建一個值類型時,總是重 載ValueType.Equals()。

你應該重載實例的Equals()函數,僅當你想改 變一個引用類型所定義的(Equals()的)語義時。.Net結構類庫中大量的類是使用 值類型的語義來代替引用類型的語義。兩個字符中對象相等,如果它們包含相同 的內容。兩個DataRowVIEwc對象相等,如果它們引用到同一個DataRow。關鍵就 是,如果你的類型須要遵從值類型的語義(比較內容)而不是引用類型的語義(比 較對象ID)時,你應該自己重載實例的Object.Equals()方法。

好了,現 在你知道什麼時候應該重載你自己的Object.Equals(),你應該明白怎樣來實現 它。值類型的比較關系有很多裝箱的實現,裝箱在原則17中討論。對於用戶類型 ,你的實例方法須要遵從原先定義行為(譯注:前面的數學相等性質),從而避免 你的用戶在使用你的類時發生一些意想不到的行為。這有一個標准的模式:

public class Foo
{
 public override bool Equals( object right )
 {
  // check null:
  // the this pointer is never null in C# methods.
  if (right == null)
   return false;
  if (object.ReferenceEquals( this, right ))
   return true;
  // Discussed below.
  if (this.GetType() != right.GetType())
   return false;
  // Compare this type's contents here:
   return CompareFooMembers(
   this, right as Foo );
 }
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved