我看到了这个哈希函数 - 它触发了一些警报:
public override int GetHashCode()
{
var result = 0;
unchecked {
result = anIntId.GetHashCode();
result *= 397 * (aString != null ? aString.GetHashCode() : 0);
}
return result;
}
我的自动哈希码气味修复子例程想要将其重写为:
public override int GetHashCode()
{
var result = 0;
unchecked {
result = anIntId.GetHashCode() * 397;
result = (result * 397) ^ (aString != null ? aString.GetHashCode() : 0);
}
return result;
}
我不记得我在哪里学到了这个模式,但似乎其中一些实际上没有意义:
这看起来正确吗,还是我犯了一些错误?
您引用的模式似乎是 FNV 哈希函数的变体。教科书上的定义是这样的:
algorithm fnv-1 is
hash := FNV_offset_basis
for each byte_of_data to be hashed do
hash := hash × FNV_prime
hash := hash XOR byte_of_data
return hash
与 FNV 相比,您的第一个示例缺少 XOR 操作。您的第二个示例更接近该算法,但您认为其中一个乘法是多余的,这是正确的。因此,回答标题问题:乘法与异或(但请注意,可以使用许多其他有效的哈希函数)。
System.HashCode
来实现这些仅引用底层字段的 GetHashCode
实现:
public override int GetHashCode() =>
HashCode.Combine(anIntId.GetHashCode(), aString.GetHashCode());
或者,更简洁,因为
anIntId
是一个整数:
public override int GetHashCode() =>
HashCode.Combine(anIntId, aString.GetHashCode());