Jad*_*ias 1 .net equals iequatable gethashcode
在.NET中,您需要Equals(object)和GetHashCode()兼容.但有时你不能:
public class GreaterThan32Bits
{
public int X { get; set; }
public int Y { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
因为数据密度大于32位,并且GetHashCode返回Int32,所以您将有3个解决方案(假设正确实现了GetHashCode):
避免将代码重复 丢弃为不正确
public override bool Equals(object other)
{
if(ReferenceEquals(null, other)) return false;
if(ReferenceEquals(this, other)) return true;
return this.GetHashCode() == other.GetHashCode();
}
Run Code Online (Sandbox Code Playgroud)与GetHashCode()分开实现Equals
public override bool Equals(object obj)
{
if(ReferenceEquals(null, other)) return false;
if(ReferenceEquals(this, other)) return true;
var other = obj as GreaterThan32Bits;
if(this.X == other.X) return this.Y == other.Y;
return false;
}
Run Code Online (Sandbox Code Playgroud)实现更高精度的GetHashCode64,重写的GetHashCode(32位)将返回(int)GetHashCode64(),而Equals将返回this.GetHashCode64()== other.GetHashCode64()
你会实施哪一个?
第一种解决方案是不精确的不正确,但更清洁.第二个选项看起来很干净,但是当类有更多属性时会变得非常复杂.第三种选择是妥协.
要求如下:if(a.Equals(b)),然后a.GetHashCode()== b.GetHashCode()
不是相反.
你不应该在GetHashCode()方面实现Equals().GetHashCode碰撞完全有效,但Equals()不得返回误报.
我建议这个实现:
public override int GetHashCode()
{
return unchecked( this.X * p1 + this.Y * p2 );
}
public override bool Equals(object obj)
{
var other = obj as GreaterThan32Bits;
// you must do the null test after the cast, otherwise the
// function crashes when obj is not a GreaterThan32Bits instance
if (ReferenceEquals(other, null)) return false;
return this.X == other.X && this.Y == other.Y;
}
Run Code Online (Sandbox Code Playgroud)
其中p1和p2是大素数.这通常会产生良好的哈希函数(少数哈希冲突 - >词典变得高效).如果X和Y值是独立的(例如,你不希望像X = Y这样的直线上有很多点),那么即使是简单的东西X ^ Y也可以是一个很好的散列函数.
但话说回来,如果你真的将这个类用作字典(或其他哈希表)中的键,那么你只需要一个好的哈希函数.
实际上,总是在GetHashCode()中返回0并且只实现Equals()是完全正确的.字典仍然可以正常使用像键这样的对象,它只是效率低下.
| 归档时间: |
|
| 查看次数: |
719 次 |
| 最近记录: |