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 值发生冲突?如果是这样,有没有简单的方法可以避免它?

C# 这是实现GetHashCode的糟糕方法吗?

根据你的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;