簡體   English   中英

是Nullable <T> .GetHashCode()一個糟糕的哈希碼函數?

[英]Is Nullable<T>.GetHashCode() a poor hash code function?

Nullable<T>.GetHashCode()的實現如下:

public override int GetHashCode()
{
    if (!this.HasValue)
    {
        return 0;
    }
    return this.value.GetHashCode();
}

但是,如果基礎值也生成哈希碼0(例如bool設置為false或int32設置為0),那么我們有兩個常見的不同對象狀態具有相同的哈希碼。 在我看來,更好的實現將是類似的。

public override int GetHashCode()
{
    if (!this.HasValue)
    {
        return 0xD523648A; // E.g. some arbitrary 32 bit int with a good mix of set and 
                           // unset bits (also probably a prime number).
    }
    return this.value.GetHashCode();
}

是的,你確實有一點意義。 如果您事先知道要存儲哪些數據,則始終可以編寫更好的GetHashCode()實現。 並不是圖書館作家所擁有的奢侈品。 但是,是的,如果你有很多布爾? 無論是假的還是!HasValue然后默認的實現會受到傷害。 枚舉和整數相同,零是一個常見值。

然而,你的論點是學術性的,改變實施成本減去一萬分,你不能自己做。 您可以做的最好是提交建議,正確的頻道是用戶語音網站 掌握這一點將是困難的,祝你好運。

讓我們首先注意這個問題只是關於性能。 對於正確性,哈希碼不需要是唯一的或抗沖突的。 但它對性能有幫助。

實際上,這是哈希表的主要價值主張:實際上均勻分布的哈希碼會導致O(1)行為。

那么哈希代碼常量最有可能導致實際應用程序中最佳的性能配置文件?

當然不是0因為0是一個常見的哈希碼: 0.GetHashCode() == 0 這適用於其他類型。 0最差的候選者,因為它往往經常發生。

那么如何避免碰撞呢? 我的建議:

static readonly int nullableDefaultHashCode = GetRandomInt32();
public override int GetHashCode()
{
    if (!this.HasValue)
        return nullableDefaultHashCode;
    else
        return this.value.GetHashCode();
}

均勻分布,不太可能發生沖突,也沒有選擇任意常數的風格問題。

注意, GetRandomInt32 可以實現為return 0xD523648A; 它仍然比return 0;更有用return 0; 但最好是查詢廉價的偽隨機數源。

最后,沒有值的Nullable<T>必須返回一個哈希碼,並且該哈希碼應該是一個常量。

返回一個任意常量可能看起來更安全或更合適,當在Nullable<int>的特定情況下查看時可能更加如此,但最后它只是:一個哈希。

Nullable<T>可以覆蓋的整個集合中(這是無限的),零不是比任何其他值更好的哈希碼。

我不明白這里的擔憂 - 在什么情況下表現不佳?

為什么你可以根據一個值的結果將哈希函數視為窮人。

我可以看到,如果Type的許多不同值散列到相同的結果,那將是一個問題。 但是null散列到與0相同的值的事實似乎無關緊要。

據我所知,.NET哈希函數最常見的用途是Hashtable,HashSet或Dictionary鍵,而零和null碰巧在同一個桶中這一事實對整體性能影響不大。

暫無
暫無

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

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