C# 这是实现GetHashCode的糟糕方法吗?
本文关键字:方法 实现 GetHashCode | 更新日期: 2023-09-27 18:34:22
我正在尝试为我已覆盖等于的对象实现GetHashCode。
public override bool Equals(object obj)
{
var myobject = obj as MyObject;
if (myobject == null)
return false;
if (myobject.SomeProperty == null || SomeProperty == null)
return false;
// All default SomeProperty's are equal
if (myobject.SomeProperty.IsDefault)
return SomeProperty.IsDefault;
// Otherwise equality is based on ID
return myobject.SomeProperty.ID == SomeProperty.ID;
}
public override int GetHashCode()
{
if (SomeProperty != null && SomeProperty.IsDefault)
return 0;
else return base.GetHashCode();
}
这是一种合理的方法,还是可能会导致与基地的碰撞。GetHashCode((?
编辑:我很欣赏迄今为止给出的解决方案,但同样的问题仍然存在。如果我没有实现完整的 GetHashCode 并依赖其他一些实现,则任一基础。GetHashCode(( 或 Guid.GetHashCode((,哈希代码是否有机会与硬编码的 0 值发生冲突?如果是这样,有没有简单的方法可以避免它?
根据你的Equals
方法,你认为一个对象的真正"身份"是SomeProperty.ID
的值,对空值/属性/等进行一些额外的处理。
这也应该反映在哈希代码中。
您应该从处理所有这些边缘情况开始,就像在Equals
方法中所做的那样。 看来你有点走上了这条路,但并没有完全到达那里。 如果对象的SomeProperty
为 null 或IsDefault
,那么它没有 ID,对我们来说,所有这些对象都是"相同的",应该具有相同的哈希代码。
之后,您需要将哈希实际基于 ID
属性,而不是利用基类的哈希代码,这就是您的 Equals
方法接下来要执行的操作。 由于ID
是一个Guid
我们知道它有一个明智的GetHashCode
实现,所以我们可以利用它,然后你就完成了:
public override int GetHashCode()
{
if (SomeProperty == null || SomeProperty.IsDefault)
return 0;
else
return SomeProperty.ID.GetHashCode();
}
或者,如果您更容易阅读,我们可以颠倒逻辑。 与其说,"如果它没有 ID,则返回零,否则返回 ID 的哈希代码",我们可以说,"如果我们有一个 ID,返回它的哈希代码,否则只返回零:
public override int GetHashCode()
{
if (SomeProperty != null && !SomeProperty.IsDefault)
return SomeProperty.ID.GetHashCode();
else
return 0;
}
我个人认为第一个与你的Equals
方法更对称,但第二个似乎更接近你想做的事情,这就是我把它扔在那里的原因。
一个好的解决方案。 文档显示
哈希函数必须具有以下属性:
如果两个对象比较相等,则每个对象的 GetHashCode 方法。 对象必须返回相同的值。但是,如果两个对象不 比较相等,两个对象的 GetHashCode 方法不 必须返回不同的值。
对象的 GetHashCode 方法必须始终返回相同的 哈希代码,只要不修改对象状态 确定对象的 Equals 方法的返回值。请注意, 这仅适用于应用程序的当前执行,并且 如果应用程序正在运行,则可以返回不同的哈希代码 再。
为了获得最佳性能,哈希函数必须生成随机 所有输入的分布。
您可能为许多不相等的对象返回 0,尽管这不会破坏租户"如果两个对象不相等,则两个对象的 GetHashCode 方法不必返回不同的值",如果太多对象返回 0,那么您将无法满足"为了获得最佳性能,哈希函数必须为所有输入生成随机分布。
另外
重写 GetHashCode 的派生类还必须重写等于 保证两个被视为相等的对象具有相同的哈希码; 否则,哈希表类型可能无法正常工作。
因此,你的实现也应该发布,以确保GetHashCode是有效的。
我建议将其更新为
public override int GetHashCode()
{
if (SomeProperty == null || SomeProperty.IsDefault)
return base.GetHashCode() ;
else return SomeProperty.ID.GetHashCode();
}
另外,为了很好地讨论GetHashCode实现,你可以看看这篇文章
。此外,在您的 Equals 中,如果您要返回的两个对象中的SomeProperty==null
false
,这是故意的吗?
或者你的意思是
if (myobject.SomeProperty == null && SomeProperty == null)
return true;
if (myobject.SomeProperty == null || SomeProperty == null)
return false;