请考虑以下代码:
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