如果一个实现GetHashCode的方式-在那里它必须这样做-由乔恩斯基特概述这里.重复他的代码:
public override int GetHashCode()
{
unchecked // Overflow is fine, just wrap
{
int hash = 17;
// Suitable nullity checks etc, of course :)
hash = hash * 23 + field1.GetHashCode();
hash = hash * 23 + field2.GetHashCode();
hash = hash * 23 + field3.GetHashCode();
return hash;
}
}
Run Code Online (Sandbox Code Playgroud)
用手滚动这个代码可以是容易出错,错误可能是微妙/很难发现(你交换+和*误?),它可能很难记住不同类型的组合规则,我不喜欢花费精神努力为不同的领域和课程一遍又一遍地写同样的东西.它还可以模糊重复噪声中最重要的细节之一(我记得包括所有字段吗?).
是否有使用.net库组合字段哈希码的简明方法?.显然我可以写自己的,但如果有一些惯用/内置的东西,我宁愿这样做.
举个例子,在Java中(使用JDK7),我可以使用以下方法实现:
@Override
public int hashCode()
{
return Objects.hash(field1, field2, field3);
}
Run Code Online (Sandbox Code Playgroud)
这确实有助于消除错误并专注于重要细节.
动机:我遇到了一个需要覆盖的C#类GetHashCode(),但它结合各种成分的哈希码的方式有一些严重的错误.用于组合哈希码的库函数对于避免这样的错误是有用的.
从 ValueType.cs
**Action: Our algorithm for returning the hashcode is a little bit complex. We look ** for the first non-static field and get it's hashcode. If the type has no ** non-static fields, we return the hashcode of the type. We can't take the ** hashcode of a static member because if that member is of the same type as ** the original type, we'll end up in an infinite loop.
今天当我使用KeyValuePair作为字典中的键(它存储了xml属性名称(枚举)和它的值(字符串))时,我被它咬了,并期望它根据其所有字段计算它的哈希码,但根据实施情况,它只考虑了关键部分.
示例(来自Linqpad的c/p):
void Main()
{
var kvp1 = …Run Code Online (Sandbox Code Playgroud) 我正在将一些东西从Java移植到C#.在Java中hashcode,a ArrayList取决于其中的项目.在C#中,我总是从List... 获得相同的哈希码
为什么是这样?
对于我的一些对象,哈希码需要不同,因为列表属性中的对象使对象不相等.我希望哈希码对于对象的状态始终是唯一的,并且当对象相等时仅等于另一个哈希码.我错了吗?
为了寻找词典的快速复合键,我遇到异常,我无法理解也无法证明.
在有限的测试中
Dictionary<KeyValuePair<UInt32, UInt32>, string>
Run Code Online (Sandbox Code Playgroud)
明显慢于(200:1)
Dictionary<KeyValuePair<UInt16, UInt16>, string>
Run Code Online (Sandbox Code Playgroud)
测试两个循环,从0到1000 Populate,然后包含ContainsKey
Poplulate ContainsKey
UInt32 92085 86578
UInt16 2201 431
Run Code Online (Sandbox Code Playgroud)
问题是
new KeyValuePair<UInt32, UInt32>(i, j).GetHashCode();
Run Code Online (Sandbox Code Playgroud)
产生许多重复.
在循环i和j 1024中,仅创建1024个唯一散列值.
基于来自CasperOne的雪崩评论尝试了i*31和j*97(两个素数),这导致105280在1024X1024上独一无二.仍然有很多重复.CasperOne我知道这与随机不一样.但随机输入并不是我的工作.GetHashCode()应该随机化输出.
为什么重复次数很多?
相同的循环
new KeyValuePair<UInt16, UInt16>(i, j).GetHashCode();
Run Code Online (Sandbox Code Playgroud)
产生1024 X 1024唯一哈希码(完美).
Int32有同样的问题.
这些重复哈希值会终止
Dictionary<KeyValuePair<UInt32, UInt32>, string>
Run Code Online (Sandbox Code Playgroud)
与Int16相比,元组还会生成很多重复项,在Int32中不会降级.
生成原始KVP和原始KPV.GetHashCode的时间类似.
与HashSet相同的异常.
Dictionary<KeyValuePair<UInt32, UInt32>, string> dKVPu32 = new Dictionary<KeyValuePair<UInt32, UInt32>, string>();
Dictionary<KeyValuePair<UInt16, UInt16>, string> dKVPu16 = new Dictionary<KeyValuePair<UInt16, UInt16>, string>();
KeyValuePair<UInt32, UInt32> kvpUint32;
KeyValuePair<UInt16, UInt16> kvpUint16;
int range = 1000;
Int32 hashCode;
HashSet<Int32> kvpUint32Hash = new HashSet<Int32>(); …Run Code Online (Sandbox Code Playgroud)