2011-09-30 55 views
8

我有下面的類IEquatables只稱爲如果基地的Equals實現覆蓋

class Product : IEquatable<Product> 
{ 
    public Guid Id { get; set; } 
    public bool Equals(Product other) 
    { 
     return Id.Equals(other.Id); 
    } 
} 

如果我試圖創建一個列表的項目的唯一列表如下

  Guid a = Guid.NewGuid(); 
     List<Product> listA = new List<Product>(); 
     listA.Add(new Product(){Id = a}); 

     List<Product> listB = new List<Product>(); 
     listB.Add(new Product() 
     { 
      Id = a 
     }); 
     Debug.Assert(listA.Union(listB).Count()==1); 

兩個項目直到我覆蓋object.Equals方法,一旦我這樣做,我的代碼如下

class Product : IEquatable<Product> 
{ 
    public Guid Id { get; set; } 
    public bool Equals(Product other) 
    { 
     if (ReferenceEquals(null, other)) return false; 
     if (ReferenceEquals(this, other)) return true; 
     return other.Id.Equals(Id); 
    } 

    public override bool Equals(object obj) 
    { 
     if (ReferenceEquals(null, obj)) return false; 
     if (ReferenceEquals(this, obj)) return true; 
     if (obj.GetType() != typeof (Product)) return false; 
     return Equals((Product) obj); 
    } 

    public override int GetHashCode() 
    { 
     return Id.GetHashCode(); 
    } 
} 

我的IEquatable Equals方法現在被調用,但只有當我重寫基本方法,此外,如果我把對象等於方法斷點它永遠不會被調用。

這是爲什麼?

---- UPDATE

所以與產品類

class Product : IEquatable<Product> 
{ 
    public Guid Id 
    { 
     get; 
     set; 
    } 
    public bool Equals(Product other) 
    { 
     return Id.Equals(other.Id); 
    } 

    public override int GetHashCode() 
    { 
     return Id.GetHashCode(); 
    } 

} 

如果GetHashCode的被刪除,IEquatable實施的Equals是從不打我明白你一般應當實現equals和GetHashCode在一起,是這是爲什麼?

+1

將'GetHashCode'實現添加到您的原始類可以獲得您想要的行爲,它看起來像。 – AakashM

回答

9

問題是在原始實現中,您並不是覆蓋GetHashcode方法。在引擎蓋下Union使用Set<T>樣式結構刪除重複項。該結構基於從GetHashCode返回的值將對象放入桶中。如果匹配相等的對象之間doesnt't(它必須這樣做),那麼他們可能會被放置在不同的桶,永不比較了Equals

一般的哈希碼,如果你實現IEquatable<T>你應該總是

  • 覆蓋Object.Equals
  • 覆蓋Object.GetHashCode

如果不這樣做既會降落在你這樣的情況。

注意,您的實現可以簡化一點

class Product : IEquatable<Product> 
{ 
    public Guid Id { get; set; } 
    public bool Equals(Product other) 
    { 
    if (ReferenceEquals(null, other)) { 
     return false; 
    } 
    return other.Id == this.Id; 
    } 

    public override bool Equals(object obj) 
    { 
    return Equals(obj as Product); 
    }  

    public override int GetHashCode() 
    { 
    return Id.GetHashCode(); 
    } 
} 
+0

這只是resharper的equals方法的默認實現。如果是這種情況,(我相信你是正確的順便說一句)爲什麼斷點沒有被打到?該用戶是否錯誤?此外,BOL在這裏http://msdn.microsoft.com/en-us/library/ms224763.aspx建議它應該查找IEquatable? –

+0

@KevHunter我更新了我的答案了一下。 – JaredPar

+0

我正在使用標準的LINQ聯合方法,上面的代碼是從一個測試用具來確認我所看到的 –

3

Enumerable.Union文件說:

默認的相等比較,默認情況下,用於比較落實的類型 值IEqualityComparer(Of T)通用接口 。要比較自定義數據類型,您需要實現此接口併爲 類型提供您自己的GetHashCode和Equals方法。

您正在執行IEquatable。您需要實施IEqualityComparer