我正在使用字典,我想覆盖GetHashCode
Key 的功能。但我需要一个 64 位的哈希码。
有什么解决办法吗?
不,你不能。的签名GetHashCode
固定为virtual int GetHashCode()
。
请注意,Dictionary<TKey, TValue>
确实处理具有相同哈希码的多个项目。您可以通过像这样重载 GetHashCode 来尝试它:
public override GetHashCode()
{
return 0;
}
这将使字典变得非常慢(它将在其中进行搜索 O(n) 而不是 O(1))!
Dictionary<,>
通过使用该方法查看每个对象来处理具有相同键的多个对象Equals
(因此这是一个两步过程,首先GetHashCode
,然后Equals
在所有具有相同键的项目之间GetHashCode
)。
要将 64 位 GetHashCode 更改为 32 位 GetHashCode,您可以简单地:
long hash64 = ....;
int hash32 = hash64.GetHashCode();
return hash32;
:-)
或者,如果您更喜欢长途:
long hash64 = ....;
unchecked
{
int hash32 = ((int)hash64) ^ ((int)(hash64 >> 32));
return hash32;
}
如果你有兴趣,这里解释了Dictionary<,>
内部是如何工作的。往下看The System.Collections.Generic.Dictionary Class
我已经对 Zobrist 哈希进行了一些研究……看来您应该简单地忽略 64 位冲突的可能性。如果你想模拟这个,你可以这样做:
public class HashPiece
{
public readonly long Hash64;
public readonly Piece[] Board = new Piece[64];
public int GetHashCode()
{
return Hash64.GetHashCode();
}
public bool Equals(object other)
{
return this.Hash64 == ((HashPiece)other).Hash64;
}
}
在此示例中,您不比较Piece[]
数组,您只希望完整的 64 位散列是正确的。显然,另一种解决方案是:
public bool Equals(object other)
{
HashPiece other2 = (HashPiece)other;
if (this.Hash64 != other2.Hash64)
{
return false;
}
return this.Board.SequenceEqual(other.Board);
}
请注意,我发现随机数生成器的质量以及使用的种子值的单个值会影响碰撞次数的轶事经验。
我使用下面的代码生成 64 位 HashCode,主要是作为长重复字符串的替代品。
public long ComputeHash(String p_sInput)
{
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
byte[] hash = md5.ComputeHash(Encoding.ASCII.GetBytes(p_sInput));
return BitConverter.ToInt64(hash, 0);
}