目前,我正在使用以下类作为我的关键字,用于对象的词典集合,这些对象由ColumnID
和可空的SubGroupID
独有:
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位整数相结合,但我不确定如何处理null SubGroupIDs
。这是我得到的,但它无效,因为SubGroupID
可以为零:
var hashKey = (long)this.ColumnID << 32 +
(this.SubGroupID.HasValue ? this.SubGroupID.Value : 0);
return hashKey.GetHashCode();
有什么想法吗?
答案 0 :(得分:3)
严格地说,你将无法完美地组合这些,因为逻辑上int?
有33位信息(整数为32位,另一位表示值是否存在)。您的非可空int
还有32位信息,总共65位,但long
只有64位。
如果您可以安全地将任意一个整数的值范围限制为仅31位,那么您就可以按原样大致打包它们。但是,你不会以这种方式获得任何优势 - 你也可以直接像这样计算哈希码(感谢Resharper的样板代码生成):
public override int GetHashCode()
{
unchecked
{
return (ColumnID*397) ^ (SubGroupID.HasValue ? SubGroupID.Value : 0);
}
}
答案 1 :(得分:2)
您似乎将GetHashCode视为唯一键。事实并非如此。 HashCodes是32位整数,并不是唯一的,只能在32位空间内良好分布,以最大限度地减少冲突的可能性。试试这个ColumnDataKey的GetHashCode方法:
ColumnID * 397 ^ (SubGroupID.HasValue ?? SubGroupID.Value : -11111111)
这里的幻数是397,一个素数,由于巫毒魔法的原因是一个很好的数字乘以混合你的位(并且是ReSharper团队选择的数字),和-11111111,一个子组ID我认为这在实践中不太可能出现。