如何处理GetHashCode()

时间:2019-05-24 07:48:50

标签: c# overflow hashcode

我正在为我的Vector类覆盖GetHashCode()函数。它仅包含3个浮点数XYZ。我想知道什么是最好的方法。

public override int GetHashCode()
{
    var sum = X + 3 * Y + 5 * Z;
    return sum.GetHashCode();
}

我需要它来快速在一个大集合中找到一个Vector。

我不想只返回X.GetHashCode(),因为这将导致对直线的相等检查过多。

当前实现的问题在于,如果浮点数很大,我可能会得到整数溢出

  • 有没有办法告诉我的编译器消除任何溢出?

  • 有更好的解决方案吗?

谢谢。

3 个答案:

答案 0 :(得分:3)

  

有没有办法告诉我的编译器消除任何溢出?

是的,您可以为此使用unchecked关键字。正如@kalimag指出的那样,只有整数值会在溢出时引发异常。

  

有更好的解决方案吗?

组合哈希值的正确方法是:

public override int GetHashCode()
{
    unchecked
    {
        int hash = 17;
        hash = hash * 23 + X.GetHashCode();
        hash = hash * 23 + Y.GetHashCode();
        hash = hash * 23 + Z.GetHashCode();

        return hash;
    }
}

有关说明,请参见this question

答案 1 :(得分:1)

通常,我们将哈希码与 xor (更好的解决方案)结合使用:

public override int GetHashCode() =>
  X.GetHashCode() ^ Y.GetHashCode() ^ Z.GetHashCode();

有关详情,请参见Why is XOR the default way to combine hashes?

xor 永远不会抛出任何异常

答案 2 :(得分:0)

当我不得不重写EqualsGetHashCode时,我通常认为我做错了。

  

我需要它来快速在一个大集合中找到一个Vector。

     

有更好的解决方案吗?

如果集合是Dictionary,怎么办?

public class Vector
{
    public int X { get; set; }
    public int Y { get; set; }
    public int Z { get; set; }
}

public class MyClass
{
    private readonly Dictionary<(int x, int y, int z), Vector> _vectors = new Dictionary<(int x, int y, int z), Vector>();

    public MyClass()
    {
        var vector1 = new Vector { X = 1, Y = 2, Z = 3 };
        var vector2 = new Vector { X = 2, Y = 3, Z = 4 };

        _vectors.Add((x: vector1.X, y: vector1.Y, z: vector1.Z), vector1);
        _vectors.Add((vector2.X, vector2.Y, vector2.Z), vector2);
    }

    public Vector FindVector(int x, int y, int z)
    {
        return _vectors[(x, y, z)];
    }
}