考虑下面的代码:
结构VEC2:IEquatable<&VEC2 GT; {双X,Y; 公共布尔等于(VEC2等) {返回X.Equals(other.X)及和放大器;并且y.equals(other.Y); } 公众覆盖布尔等于(obj对象) {如果(obj是VEC2) {返回等于((VEC2 )OBJ) } 返回FALSE; } //这将返回当X,Y被交换公共覆盖INT GetHashCode()方法相同的值 {返回X.GetHashCode ()^ Y.GetHashCode(); } }
除了比较双打的谈话平等(这只是演示代码),我所关心的是,有一个哈希冲突时,X,Y值交换。例如:
VEC2 A =新VEC2(){X = 1,Y = 5}; VEC2 B =新VEC2(){X = 5,Y = 1}; 布尔TEST1 = A.Equals(B); //返回false; 布尔测试2 = A.GetHashCode()== B.GetHashCode()//返回true !!!!!
这应该在字典中收集造成严重破坏。所以,问题是如何物业形成的GetHashCode()功能2,3甚至4浮点值,这样的结果是不是对称的,哈希值不冲突
编辑1:点实施不适当的 X ^是解决方案和的PointF 包裹 ValueType.GetHashCode()。
长方形拥有非常奇特(((X ^(( Y'LT;&; 13)|(Y'GT;> 19)))^((宽度与所述;&下; 26)|(宽>&→6)))^((高度&所述; 7;)| (身高>> 25)))的散列码,这似乎达到预期效果的表达
编辑2:System.Double有一个很好的实现,因为它没有考虑每一位同样重要
公众覆盖不安全INT的GetHashCode()//从System.Double {双击NUM =这一点; 如果(NUM == 0.0) {返回0; } 长NUM2 = *((长×)及NUM); 返回(((int)的NUM2)^((int)的(NUM2>> 32))); }解决方案
乔恩斯基特有这个涵盖:
的什么是一个重写System.Object.GetHashCode最好的算法?
公共覆盖INT的GetHashCode() {选中//溢出是好的,只是包装 { INT哈希= 17; //适用无效支票当然:) 哈希等=散* 23 + X.GetHashCode(); 散列=散列* 23 + Y.GetHashCode(); 返回哈希; } }
另外,请更改等于(对象)实施
回等号(OBJ为FVector2);
不过请注意,这可能会察觉到一个派生类型相等。如果你不希望出现这种情况,你不得不进行比较的运行时类型 other.GetType()与 typeof运算(FVector2)(不要忘记无效检查) 感谢您指出它是一个结构,LukH
ReSharper的具有良好代码生成平等和哈希码,所以如果你有ReSharper的你可以让它做它的事。
Consider the following code:
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(); } }Beyond the conversation of comparing doubles for equality (this is just demo code), what I am concerned with is that there is a hash clash when X, Y values are swapped. For example:
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 !!!!!which should wreck havoc in a dictionary collection. So the question is how to property form the GetHashCode() function for 2,3 or even 4 floating point values such that the results are not symmetric and the hashes don't clash.
Edit 1:Point implements the inappropriate x ^ y solution, and PointF wraps ValueType.GetHashCode().
Rectangle has a very peculiar (((X ^ ((Y << 13) | (Y >> 19))) ^ ((Width << 26) | (Width >> 6))) ^ ((Height << 7) | (Height >> 25))) expression for the hash code, which seems to perform as expected.
Edit 2:'System.Double' has a nice implementation as it does not consider each bit equally important
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 has this covered:
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; } }Also, change your Equals(object) implementation to:
return Equals(obj as FVector2);Note however that this could perceive a derived type to be equal. If you don't want that, you'd have to compare the runtime type other.GetType() with typeof(FVector2) (and don't forget nullity checks) Thanks for pointing out it's a struct, LukH
Resharper has nice code generation for equality and hash code, so if you have resharper you can let it do its thing
更多推荐
什么是适当的`的GetHashCode()`算法的二维结构点(避免冲突)
发布评论