2010-08-31 31 views
0

目前我使用下面的類作爲我對通過ColumnID是唯一對象的詞典收集和鍵可爲空SubGroupID獲取哈希碼的int和可空<int>對

public class ColumnDataKey 
{ 
    public int ColumnID { get; private set; } 
    public int? SubGroupID { get; private set; } 

    // ... 

    public override int GetHashCode() 
    { 
     var hashKey = this.ColumnID + "_" + 
      (this.SubGroupID.HasValue ? this.SubGroupID.Value.ToString() : "NULL"); 
     return hashKey.GetHashCode(); 
    } 
} 

我想不知怎麼把這個結合到一個64位整數,但我不知道如何處理空SubGroupIDs。這是據我得到的,但它也不是一個有效SubGroupID可以爲零:

var hashKey = (long)this.ColumnID << 32 + 
    (this.SubGroupID.HasValue ? this.SubGroupID.Value : 0); 
return hashKey.GetHashCode(); 

任何想法?

+0

@downvoter - 爲什麼? – Codesleuth 2013-06-11 22:24:46

回答

3

嚴格地說,你將無法將這些完美地結合起來,因爲邏輯上int?有33位信息(32位表示整數,另一位表示值是否存在)。您的不可爲空int具有信息總共製造65位的進一步的32位,但一個long只有64位。

如果你可以安全地限制任一整數的只有31位的數值範圍內,那麼你可以粗略地收拾他們爲你已經做。但是,你不會得到任何優勢做這樣 - 你可能也只是計算散列碼直接像這樣(感謝ReSharper的樣板代碼生成):

public override int GetHashCode() 
{ 
    unchecked 
    { 
     return (ColumnID*397)^(SubGroupID.HasValue ? SubGroupID.Value : 0); 
    } 
} 
+0

我明白了,很好的回答!我正在研究'SubGroupID'的範圍 - 它看起來像它永遠不會低於零,所以我希望這意味着我可以剝下它一點,並使用最後一位意味着'空'? – Codesleuth 2010-08-31 10:35:43

+0

這就像一個魅力!按照Matt的建議,我將零更改爲-11,111,111,但基本上我已經使用了您的答案。謝謝! – Codesleuth 2010-08-31 10:52:55

2

你似乎在思考的GetHashCode作爲唯一鍵。事實並非如此。 HashCodes是32位整數,並不意味着是唯一的,只有在32位空間中分佈良好才能將衝突概率降至最低。嘗試此ColumnDataKey你的GetHashCode方法:這裏

ColumnID * 397^(SubGroupID.HasValue ?? SubGroupID.Value : -11111111) 

神奇的數字是397,一個素數,這對於巫術的原因是一個很好的數目乘以混淆了你的比特(並且是多少ReSharper團隊選擇)和-11111111,我認爲這是我認爲在實踐中不太可能出現的子集團ID。

+0

這似乎甚至不會在實踐中出現-1。我會盡量把你的答案和丹尼爾的結合起來。 – Codesleuth 2010-08-31 10:45:55