64 位 gethashcode 是否可用于对象?

Mas*_*oud 2 c# 64-bit hashcode

我正在使用字典,我想覆盖GetHashCodeKey的功能。但我需要一个 64 位哈希码。

有什么解决办法吗?

xan*_*tos 6

不,你不能。的签名GetHashCode固定为virtual int GetHashCode()

请注意,Dictionary<TKey, TValue> 使用相同的哈希码处理多个项目。您可以通过像这样重载 GetHashCode 来尝试它:

public override GetHashCode()
{
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这将使字典变得非常慢(它将在其中搜索 O(n) 而不是 O(1))!

Dictionary<,>通过查看与所述的每一个与手柄相同的密钥多个对象Equals方法(因此它是一个两步的过程中,首先GetHashCode,然后Equals都具有相同的项目之间GetHashCode)。

要将 64 位 GetHashCode 更改为 32 位 GetHashCode,您只需:

long hash64 = ....;
int hash32 = hash64.GetHashCode();
return hash32;
Run Code Online (Sandbox Code Playgroud)

:-)

或者,如果您喜欢长途旅行:

long hash64 = ....;

unchecked
{
    int hash32 = ((int)hash64) ^ ((int)(hash64 >> 32));
    return hash32;
}
Run Code Online (Sandbox Code Playgroud)

如果你有兴趣,这里解释了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;
    }
}
Run Code Online (Sandbox Code Playgroud)

在这个例子中,你不比较Piece[]数组,你只是希望完整的 64 位散列是正确的。显然另一个解决方案是:

    public bool Equals(object other)
    {
        HashPiece other2 = (HashPiece)other;

        if (this.Hash64 != other2.Hash64)
        {
            return false;
        }

        return this.Board.SequenceEqual(other.Board);
    }
Run Code Online (Sandbox Code Playgroud)

请注意,我发现anecdotical经验是随机数发生器的质量,使用的种子值的同一值,可以影响冲突的数量。