Ben*_*Ben 1 c# equality gethashcode
在这个MSDN页面中,它说:
警告:
如果重写GetHashCode方法,则还应该重写Equals,反之亦然.如果在对两个对象进行相等性测试时,重写的Equals方法返回true,则重写的GetHashCode方法必须为两个对象返回相同的值.
我也看到了许多类似的建议,我可以理解,当重写Equals方法时,我也想要覆盖GetHashCode.据我所知,GetHashCode与哈希表查找一起使用,这与等式检查不同.
这是一个帮助解释我想问的例子:
public class Temperature /* Immutable */
{
public Temperature(double value, TemperatureUnit unit) { ... }
private double Value { get; set; }
private TemperatureUnit Unit { get; set; }
private double GetValue(TemperatureUnit unit)
{
/* return value converted into the specified unit */
}
...
public override bool Equals(object obj)
{
Temperature other = obj as Temperature;
if (other == null) { return false; }
return (Value == other.GetValue(Unit));
}
public override int GetHashCode()
{
return Value.GetHashCode() + Unit.GetHashCode();
}
}
Run Code Online (Sandbox Code Playgroud)
在这个例子中,两个温度对象被认为是相等的,即使它们没有在内部存储相同的东西(例如295.15 K == 22摄氏度).目前,GetHashCode方法将为每个方法返回不同的值.这两个温度对象是相同的,但它们也不相同,所以它们具有不同的哈希码是不正确的?
当在哈希表中存储值时,例如Dictionary<>,框架将首先调用GetHashCode()并检查哈希表中是否已存在该哈希码的桶.如果有,它将调用.Equals()以查看新值是否确实等于现有值.如果不是(意味着两个对象不同,但导致相同的哈希码),则会产生所谓的冲突.在这种情况下,该桶中的项目被存储为链表,并且检索特定值变为O(n).
如果您实施GetHashCode()却并没有实现Equals(),该框架将诉诸使用参考平等检查,这将导致每一个平等的情况下产生的碰撞.
如果您实施Equals()却并没有实现GetHashCode(),你可以在这里你有这样的人相等的两个对象,但造成了不同的散列码意味着他们会保持在你的哈希表自己独立的价值观碰到的情况.这可能会让使用您班级的人感到困惑.
至于哪些对象被认为是平等的,那取决于你.如果我根据温度创建哈希表,我是否应该使用其摄氏度或华氏度值来引用相同的项目?如果是这样,他们需要产生相同的哈希值并且 Equals()需要返回true.
更新:
让我们退后一步,首先看一下哈希码的用途.在此上下文中,哈希码用作识别两个对象是否最可能相等的快速方法.如果我们有两个具有不同哈希码的对象,我们知道它们不相等.如果我们有两个具有相同哈希码的对象,我们知道它们很可能是相等的.我之所以说很可能是因为int只能用来表示几十亿个可能的值,而字符串当然可以包含Charles Dickens的全部作品,或者任意数量的可能值..NET框架中的许多内容都基于这些事实,使用代码的开发人员会认为事情的工作方式与框架的其余部分一致.
如果你有两个具有不同哈希码的实例,但是实现的Equals()返回为true,那么你就违反了这个约定.比较两个对象的开发人员可能会使用其中一个对象来引用哈希表中的键,并期望获得现有值.如果哈希代码突然不同,则此代码可能会导致运行时异常.或者可能返回对完全不同的对象的引用.
295.15k和22C在你的程序范围内是否相等是你的选择(在我看来,它们不是).但是,无论你决定什么,相同的对象必须返回相同的代码.