簡體   English   中英

為沒有字段的值對象覆蓋GetHashCode()

[英]Overriding GetHashCode() for value objects without fields

有時我需要沒有字段的值對象(消息頭,模式等),例如:

abstract class RequestHeader
{
}

sealed class FirstRequestHeader : RequestHeader
{
}

我在類似的方法中使用它們:

partial class Server
{
    private readonly IReadOnlyDictionary<RequestHeader, Action<object>> requestMap;

    public void ProcessRequest(RequestHeader header, object request)
    {
        requestMap[header](request);
    }
}

在這種情況下, GetHashCodeEquals方法的默認實現完全符合我的需求,因為我可以使用單例。

但是由於FirstRequestHeader是一個不可變的值對象,所以我希望它的行為類似於真實值對象:

var a = new FirstRequestHeader();
var b = new FirstRequestHeader();
Console.WriteLine(a == b &&
    a.Equals(b) &&
    a.GetHashCode() == b.GetHashCode()); // False, but should be True

覆蓋==運算符和Equals方法很容易。

但是在這種情況下,重寫GetHashCode方法的正確或推薦方法是什么?

我可以期待一些答案(都有缺點):

  • 每種類型的硬編碼常量哈希碼
  • 每次執行時生成一個並將其保存在靜態字段中
  • 通過GetType方法使用類型的哈希碼
  • 避免空對象(添加字段)

但是沒有通過搜索確認任何假設

那么,你會怎么做?

如果沒有與該類關聯的數據,則僅創建一個實例。

sealed class FirstRequestHeader : RequestHeader
{
    public static readonly FirstRequestHeader Value = new FirstRequestHeader();

    private FirstRequestHeader()
    {

    }
}

每種類型的硬編碼常量哈希碼

如果您希望兩個“相同”的對象被視為相等(並且沒有字段或您的實例相同),那么這絕對是正確的方法。

添加一個新字段(我認為您不會以任何有意義的方式對其進行修改)會導致相同的結果,只會使此過程變得過於復雜。 對於其他兩種方法可以說相同。

請注意,您可以選擇任何值-您不必擔心不同類型之間可能發生的哈希碼沖突,因此請保持簡單。

如果希望所有實例具有相同的哈希碼而不使用常量,則還可以使用以下類型的哈希碼:

    public class FirstRequestHeader
    {
        public override int GetHashCode()
        {
            return this.GetType().GetHashCode();
        }
    }

暫無
暫無

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

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