【发布时间】:2016-04-21 11:02:40
【问题描述】:
在this 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();
}
}
在这个例子中,两个温度对象被认为是相等的,即使它们内部没有存储相同的东西(例如 295.15 K == 22 摄氏度)。目前 GetHashCode 方法将为每个返回不同的值。这两个温度对象相等但也不相同,所以它们具有不同的哈希码是不正确的吗?
【问题讨论】:
-
如果您永远不会将您的
Temperature对象存储在HashSet或Dictionary中,那么您可以 忽略GetHashCode,但是你真的,真的不应该。这将是一种可怕的做法。 -
-
@IvanStoev:当然,这确实说明了为什么不应该这样做。您可能确信您没有将某些内容放入
HashSet,但是,尤其是对于 LINQ 之类的东西,您不能确定其中一个的内部实现是否使用了 HashCode(几乎可以肯定是) . -
只是为了澄清我正在尝试实现两者。
-
@Ben:您确实需要区分在温度测量的物理世界中平等意味着什么,以及在 C# 代码世界中平等意味着什么。如果您的
Equals方法返回true,那么这两个对象必须 返回相同的哈希码。如果他们不这样做,您的代码将以许多令人沮丧的有趣方式中断......
标签: c# equality gethashcode