2009-02-03 40 views
15

下面是一個覆蓋Object.Equals()的示例實現,用於應用程序中所有其他實體從中派生的實體基類。實體類的GetHashCode()的正確實現是什麼?

所有的實體類都有屬性Id,它是一個可爲空的int。 (這是無論什麼表的實體類對應的主鍵。)

public override bool Equals(object obj) 
     { 
      if (obj == null || GetType() != obj.GetType()) 
       return false; 

      if (base.Equals(obj)) 
       return true; 

      return Id.HasValue && ((EntityBase) obj).Id.HasValue && 
        Id.Value == ((EntityBase) obj).Id.Value; 
     } 

鑑於此實現equals()方法中,你如何正確地實現GetHashCode()方法?

+0

對於記錄來說,對於一個ID有一個可爲空的int是一個可怕的想法。 ID應該幾乎總是GUID,絕對不能爲空。 – 2014-08-28 15:52:18

回答

23

如果你從一些已經覆蓋GetHashCode獲得我實現它:

public override int GetHashCode() 
{ 
    unchecked 
    { 
     int hash = 37; 
     hash = hash * 23 + base.GetHashCode(); 
     hash = hash * 23 + Id.GetHashCode(); 
     return hash; 
    } 
} 

身份證件的空值將Id.GetHashCode返回0()。

如果你的類只是從Object派生,我剛剛回到Id.GetHashCode() - 你想在你的哈希碼的object.GetHashCode實施,基本上最終被對象標識。

請注意,如果兩個實體都沒有Id,但您的相等定義將不會返回true但是兩個對象都返回相同的哈希碼。你不妨考慮改變你的Equals實現。

+9

對於那些想知道的問題,就像我做的那樣:23和37是任意數字,它們是共素數。喬恩在這裏回答了類似的答案:http://www.eggheadcafe.com/software/aspnet/29483139/override-gethashcode.aspx – 2009-02-03 17:57:49

1

如果Id屬性在實例的生命週期中不可改變(或至少在需要使用其哈希值的時間內,例如在對象位於地圖或其他集合中時需要使用GetHashCode(),散列)。

假設它是這樣,您可以使用Id的值作爲所有有效值的哈希值,然後對null使用固定哈希值。我不記得最適合這個的是什麼,但是我會假設一個隨機選擇的值爲null(在編譯之前隨機選擇,不是在運行時)或者值的有效值的中間值(即0和int之間的一半。最大)。

+1

它不一定是永生不變的 - 只能從第一次插入地圖或其他地方的時候開始。可以創建一個實例,解決它,將其放入地圖,然後*停止混亂。 – 2009-02-03 17:48:42

+0

這是一個公平的觀點。我會做一個編輯。 – 2009-02-03 17:51:41

2

什麼喬恩斯基特回答是一個很好的解決方案,但是,你可能要添加一個未檢查的代碼塊,使整數溢出

unchecked 
{ 
    int hash = ...; 
    return hash 
} 

https://msdn.microsoft.com/en-us/library/khy08726(v=vs.140).aspx

如果沒有選中,也不指定選中,默認上下文取決於外部因素,如編譯器選項。

我還想補充一點,在POCO上使用base.GetHashCode()將會調用默認的object.GetHashCode。這絕對不是你想要的...

2

如何使用該類型作爲散列碼的一部分?
這是一個很好的實現嗎?

public class Foo 
{ 
    public int Id { get; set; } 

    // other properties here 
    // ...... 

    public override int GetHashCode() 
    { 
     int hash = 37; 
     hash = hash * 23 + typeof(Foo).GetHashCode(); 
     hash = hash * 23 + Id.GetHashCode(); 
     return hash; 
    } 
} 
相關問題