簡體   English   中英

實體類的GetHashCode()的正確實現是什么?

[英]What is the correct implementation for GetHashCode() for entity classes?

下面是一個覆蓋實體基類的Object.Equals()的示例實現,應用程序中的所有其他實體都從該實體基類派生。

所有實體類都具有屬性Id,它是一個可以為null的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()?

如果您從已經覆蓋GetHashCode內容派生,我將其實現為:

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

對於Id.GetHashCode(),Id的空值將返回0。

如果您的類只是從Object派生,我剛剛返回Id.GetHashCode() -你希望包括object.GetHashCode在你的哈希碼實現,因為這基本上結束是對象的身份。

請注意,如果兩個實體都沒有Id,則您的相等定義將不會返回true ,但是將從兩個對象返回相同的哈希碼。 您可能希望考慮更改您的Equals實施。

Jon Skeet回答的是一個很好的解決方案,但是,您可能希望添加一個未經檢查的代碼塊以允許整數溢出

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

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

如果既未指定也未取消選中,則默認上下文取決於外部因素,例如編譯器選項。

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

將類型用作哈希碼的一部分怎么樣?
這是一個很好的實施嗎?

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;
    }
}

如果Id屬性在實例的生命周期中是不可變的(或者至少在其哈希需要使用的時間,例如當對象在地圖或其他需要哈希的集合中時GetHashCode()則只能正確實現GetHashCode() )。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM