簡體   English   中英

C#這是實現GetHashCode的不好方法嗎?

[英]C# Is this a bad way to implement GetHashCode?

我正在嘗試為覆蓋Equals的對象實現GetHashCode。

public override bool Equals(object obj)
{
    var myobject = obj as MyObject;
    if (myobject == null)
        return false;

    if (myobject.SomeProperty == null || SomeProperty == null)
        return false;

    // All default SomeProperty's are equal
    if (myobject.SomeProperty.IsDefault)
        return SomeProperty.IsDefault;

    // Otherwise equality is based on ID
    return myobject.SomeProperty.ID == SomeProperty.ID;
}

public override int GetHashCode()
{
    if (SomeProperty != null && SomeProperty.IsDefault)
        return 0;
    else return base.GetHashCode();
}

這是一種合理的方法,還是可能導致與base.GetHashCode()的沖突?

編輯:我感謝到目前為止給出的解決方案,但仍然存在相同的問題。 如果我沒有實現完整的GetHashCode並依賴於base.GetHashCode()或Guid.GetHashCode()的其他實現,那么哈希代碼是否有可能與硬編碼0值沖突? 如果是這樣,有沒有一種簡單的方法可以避免這種情況?

根據您的Equals方法,您認為真正是對象的“身份”的是SomeProperty.ID的值,還需要對null值/ properties / etc進行一些其他處理。

這也應該反映在哈希碼中。

您應該像處理Equals方法一樣開始處理所有這些極端情況。 好像您有點兒走這條路,但還沒到那兒。 如果對象的SomeProperty為null IsDefault則它沒有ID,對我們來說,所有此類對象都是“相同的”,並且應具有相同的哈希碼。

不過,在那之后,您無需真正利用基類的哈希碼,而需要將哈希實際基於ID屬性,這是您的Equals方法接下來要做的。 由於IDGuid我們知道它具有明智的GetHashCode實現,因此我們可以利用它,然后完成了:

public override int GetHashCode()
{
    if (SomeProperty == null || SomeProperty.IsDefault)
        return 0;
    else 
        return SomeProperty.ID.GetHashCode();
}

或者,如果您更容易閱讀,我們可以顛倒邏輯。 與其說“如果沒有ID,則返回零,否則返回ID的哈希碼”,我們可以說:“如果有ID,則返回其哈希碼,否則僅返回零:

public override int GetHashCode()
{
    if (SomeProperty != null && !SomeProperty.IsDefault)
        return SomeProperty.ID.GetHashCode();
    else 
        return 0;
}

我個人認為第一個與您的Equals方法具有更多的對稱性,但是第二個似乎與您嘗試執行的操作更加接近,這就是為什么我將它扔在那里的原因。

那不是一個好的解決方案。 文檔顯示

哈希函數必須具有以下屬性:

如果兩個對象比較相等,則每個對象的GetHashCode方法必須返回相同的值。 但是,如果兩個對象的比較不相等,則兩個對象的GetHashCode方法不必返回不同的值。

只要沒有修改確定對象的Equals方法返回值的對象狀態,對象的GetHashCode方法就必須始終返回相同的哈希碼。 請注意,這僅適用於當前執行的應用程序,並且如果再次運行該應用程序,則可以返回不同的哈希碼。

為了獲得最佳性能,哈希函數必須為所有輸入生成隨機分布。

您可能會為許多不相等的對象返回0,盡管這不會破壞租戶“如果兩個對象的比較不相等,則兩個對象的GetHashCode方法不必返回不同的值”,如果太多的對象返回0,則您不會滿足“為獲得最佳性能,散列函數必須為所有輸入生成隨機分布。”

此外,

重寫GetHashCode的派生類也必須重寫Equals,以確保被認為相等的兩個對象具有相同的哈希碼。 否則,哈希表類型可能無法正常工作。

因此,還應發布您正在執行的Equals,以確保GetHashCode有效。

我建議將其更新為

public override int GetHashCode()
{
    if (SomeProperty == null || SomeProperty.IsDefault)
        return base.GetHashCode() ;
    else return SomeProperty.ID.GetHashCode();
}

另外,為了更好地討論GetHashCode實現,您可以查看這篇文章

另外,在相等中,如果兩個對象中的SomeProperty==null都返回false ,那是故意的嗎?

還是你的意思

if (myobject.SomeProperty == null && SomeProperty == null)
    return true;
if (myobject.SomeProperty == null || SomeProperty == null)
    return false;

暫無
暫無

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

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