2010-11-06 112 views
7

我正面臨着GetHashCode和Equals的問題,這些問題我已被一個類覆蓋。我使用運算符==來驗證兩者是否相等,如果它們的哈希碼相同以便驗證它們確實相等,我預計這將調用GetHashCode和Equals。C#GetHashCode /等於重寫不被調用

但令我吃驚的是,既沒有被調用,平等測試的結果也是錯誤的(儘管它應該是真的)。

覆蓋代碼:

public class User : ActiveRecordBase<User> 

     [...] 

     public override int GetHashCode() 
     { 
      return Id; 
     } 

     public override bool Equals(object obj) 
     { 
      User user = (User)obj; 
      if (user == null) 
      { 
       return false; 
      } 

      return user.Id == Id; 
     } 
    } 

相等性檢查:

if (x == y) // x and y are both of the same User class 
    // I'd expect this test to call both GetHashCode and Equals 
+4

如果'其實=='沒打電話給你'Equals'方法,那麼它會導致堆棧溢出,因爲它使用了''==操作符的對象... – Guffa 2010-11-06 23:05:40

+0

沒有什麼代碼你表明需要調用GetHashCode()。只有在您將對象用作集合的關鍵字時纔會調用它。 – RenniePet 2014-06-29 02:12:56

回答

11

==是從任一.GetHashCode().Equals()完全分開的。

你可能會感興趣的Microsoft Guidelines for Overloading Equals() and Operator ==

簡短版本是:使用.Equals()來實現等於比較。使用運算符==代替標識比較,或者如果您要創建不可變類型(其中每個平等實例可以被認爲是有效的相同)。此外,.Equals()是一種虛擬方法,可以被子類覆蓋,但運算符==取決於使用它的表達式的編譯時類型。

最後,爲了保持一致,請在執行.Equals()時執行.GetHashCode()。超載運營商!=任何時候您超載運營商==

+0

我的對象是可變的。我期望調用==運算符實際上會調用Equals方法,但我不明白爲什麼它現在不起作用,並且它在以前工作... – tomzx 2010-11-06 22:53:52

+0

@tomzx:'= ='操作符永遠不會調用'.Equals()'方法,除非你重載它。 – 2010-11-06 22:54:43

+1

@Daniel您的建議重新「==」是不正確的。微軟一貫表示,如果你想要IDENTITY比較,你必須使用「ReferenceEquals」。例如,考慮字符串。如果您使用字符串生成器來創建兩個字符串具有相同CONTENTS但不同的ADDRESSES,則「==」將返回TRUE(相等比較),但ReferenceEquals將返回FALSE。 「==」通常被認爲是平等的比較,通常被實現爲做任何類的EQUALS。 – ToolmakerSteve 2013-09-26 19:47:18

1

也許在User類中增加一個方法。

public virtual bool Equals(User other) 
    { 
     if (ReferenceEquals(null, other)) return false; 
     if (ReferenceEquals(this, other)) return true; 
     return other.Id == Id; 
    }