c# – 对于2D点结构体来说,什么是适当的“GetHashCode()”算法(避免冲突)

前端之家收集整理的这篇文章主要介绍了c# – 对于2D点结构体来说,什么是适当的“GetHashCode()”算法(避免冲突)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
请考虑以下代码
struct Vec2 : IEquatable<Vec2>
{
    double X,Y;

    public bool Equals(Vec2 other)
    {
        return X.Equals(other.X) && Y.Equals(other.Y);
    }

    public override bool Equals(object obj)
    {
        if (obj is Vec2)
        {
            return Equals((Vec2)obj);
        }
        return false;
    }

    // this will return the same value when X,Y are swapped
    public override int GetHashCode()
    {
        return X.GetHashCode() ^ Y.GetHashCode();
    }

}

除了比较双重平等的对话(这只是演示代码),我关心的是当X,Y值被交换时,有一个哈希冲突.例如:

Vec2 A = new Vec2() { X=1,Y=5 };
Vec2 B = new Vec2() { X=5,Y=1 };

bool test1 = A.Equals(B);  // returns false;
bool test2 = A.GetHashCode() == B.GetHashCode() // returns true !!!!!

这应该在字典集合中破坏破坏.所以问题是如何为2,3或甚至4个浮点值形成GetHashCode()函数,以使结果不对称,并且哈希值不会冲突.

编辑1:

Point实现不适当的x ^ y解,PointF包装ValueType.GetHashCode().

矩形具有非常特殊的((X((Y <13)|(Y> 19)))((宽度<26)|(宽度> 6)) )^((高度< 7)|(高度>> 25)))表达式,这似乎按预期的方式执行.

编辑2:

‘System.Double’有一个很好的实现,因为它不认为每个位都同样重要

public override unsafe int GetHashCode() //from System.Double
{
    double num = this;
    if (num == 0.0)
    {
        return 0;
    }
    long num2 = *((long*) &num);
    return (((int) num2) ^ ((int) (num2 >> 32)));
}

解决方法

Jon skeet有这个涵盖:

What is the best algorithm for an overridden System.Object.GetHashCode?

public override int GetHashCode()
   {
       unchecked // Overflow is fine,just wrap
       {
           int hash = 17;
           // Suitable nullity checks etc,of course :)
           hash = hash * 23 + X.GetHashCode();
           hash = hash * 23 + Y.GetHashCode();
           return hash;
       }
   }

另外,将您的Equals(object)实现更改为:

return Equals(obj as FVector2);

然而,请注意,这可以感知派生类型相等.如果你不想这样做,你必须比较其他类型的类型(.GetType()与typeof(FVector2)(并且不要忘记无效检查)感谢指出它是一个结构体,LukH

Resharper有一个很好的代码生成相等和哈希码,所以如果你有resharper,你可以让它做它的事情

猜你在找的C#相关文章