2011-05-12 54 views
9

實現自定義類實例比較時,我們是否應該覆蓋EqualsGetHashCode屬性?當比較對象時等於vs GetHashCode

在下面的代碼中我有一個類的集合。類別AID,類別B-由Code進行比較。

using System; 
using System.Collections.Generic; 
using System.Diagnostics; 
using System.Linq; 

namespace ConsoleApplication2 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      List<I> bars = new List<I>(); 
      bars.Add(new A() { Id = 1, Code = "one A" }); 
      bars.Add(new B() { Id = 1, Code = "one B" }); 
      bars.Add(new A() { Id = 1, Code = "one A+" }); 
      bars.Add(new B() { Id = 1, Code = "one B" }); // Code = "one B+" 

      var distictBars = bars.Distinct(); 

      foreach (var item in distictBars) 
      { 
       Debug.WriteLine(item.Code); 
      } 
     } 
    } 

    interface I 
    { 
     string Code { get; set; } 
    } 

    class A : I, IEquatable<A> 
    { 
     public int Id { get; set; } 
     public string Code { get; set; } 

     public bool Equals(A other) 
     { 
      // this is the ??? comparison 
      return this.Id == other.Id; 
      //return this.Code == other.Code; 
     } 

     public override bool Equals(object obj) 
     { 
      if (obj is A) 
       return this.Equals(obj as A); 
      else 
       return object.ReferenceEquals(this, obj); 
     } 

     public override int GetHashCode() 
     { 
      // this is the wanted comparison 
      return this.Id; 
     } 
    } 

    class B : I, IEquatable<B> 
    { 
     public int Id { get; set; } 
     public string Code { get; set; } 

     public bool Equals(B other) 
     { 
      // this is the ??? comparison 
      return this.Id == other.Id; 
     } 

     public override bool Equals(object obj) 
     { 
      if (obj is B) 
       return this.Equals(obj as B); 
      else 
       return object.ReferenceEquals(this, obj); 
     } 

     public override int GetHashCode() 
     { 
      // this is the wanted comparison 
      return this.Code.GetHashCode(); 
     } 
    } 
} 

輸出是:

one A 
one B 

的情況下,評論Code = "one B+"輸出

one A 
one B 
one B+ 

現在我問自己什麼,我應該在B類,如果它覆蓋Equals似乎這對比較沒有影響?

GetHasCode()重寫足夠的那種比較?

+0

的可能重複[我有沒有正確實現的equals()/ GetHashCode()方法?(http://stackoverflow.com/questions/5700099/have-i-implemented-equals-gethashcode-correctly) – 2011-05-12 17:46:36

回答

12

以下是您需要了解的關於EqualsGetHashCode之間的關係。

散列表使用散列表快速查找元素預期存在的「存儲區」。 如果元素存在於兩個不同的桶中,則假設是它們不能相等。

這樣做的結果是,你應該查看哈希代碼,以確定唯一性的目的,作爲一個快速檢查:即,如果兩個對象具有不同的散列碼,他們相同(不管他們的Equals方法返回什麼)。

如果兩個對象具有相同的散列碼,它們將駐留在散列表的同一個存儲桶中。 然後他們的Equals方法將被調用以確定相等性。

因此GetHashCode必須返回相同的值爲兩個對象,你想被視爲相等。

4

你總是需要重寫它們在一起和兼容的實現。散列碼匹配/不匹配意味着(分別)「可能的平等」和「不相等」。散列碼本身並不表示相等。因此,在發現哈希碼匹配(或用於創建值組)之後,仍檢查Equals以確定匹配。

如果兩者不同意,你可能永遠找不到匹配。

3

Distinct方法將使用GetHashCode方法確定項目之間的不等式,並使用Equals方法確定相等性。

它首先使用散列碼進行快速比較,以確定哪些項目絕對不相等,即具有不同的散列碼,然後比較具有相同散列碼的項目以確定哪些項目確實相等。

在您執行B類時,您有一個不一致的GetHashCodeEquals方法的實現,所以比較將無法正常工作。您的兩個B對象具有不同的哈希碼,因此它們不會相互比較。兩個被認爲是相等的項目也應該返回相同的哈希碼。

如果一個類實現IEquatable<T>接口,將使用Equals(T)方法,否則將使用Equals(object)方法。