-1

我正在尝试为已覆盖 Equals 的对象实现 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();
}

这是一种合理的方法吗,还是可能导致与 base.GetHashCode() 发生冲突?

编辑:我很欣赏迄今为止给出的解决方案,但同样的问题仍然存在。如果我没有实现完整的 GetHashCode 并依赖于其他一些实现,无论是 base.GetHashCode() 还是 Guid.GetHashCode(),是否有可能与硬编码的 0 值发生哈希码冲突?如果是这样,有没有一种简单的方法可以避免它?

4

2 回答 2

3

根据您的Equals方法,您认为真正是对象的“身份”的是 的值SomeProperty.ID,以及对空值/属性/等的一些额外处理。

这也应该反映在哈希码中。

您应该开始处理所有这些边缘情况,就像您在Equals方法中所做的那样。看起来你有点走这条路,但没有完全到达那里。如果对象SomeProperty为空IsDefault没有 ID,那么对我们来说,所有这些对象都是“相同的”并且应该具有相同的哈希码。

不过,在那之后,您需要将哈希实际基于属性,而不是利用基类的哈希码,ID这就是您的Equals方法接下来要做的事情。因为我们知道它有一个合理的ID实现,所以我们可以利用它,然后你就完成了:GuidGetHashCode

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,但第二个似乎更接近你想要做的,这就是我把它扔在那里的原因。

于 2013-10-07T20:17:41.970 回答
1

这不是一个好的解决方案。文档显示_

哈希函数必须具有以下属性:

如果两个对象比较相等,则每个对象的 GetHashCode 方法必须返回相同的值。但是,如果两个对象比较不相等,则两个对象的 GetHashCode 方法不必返回不同的值。

只要确定对象的 Equals 方法的返回值的对象状态没有修改,对象的 GetHashCode 方法就必须始终返回相同的哈希码。请注意,这仅适用于应用程序的当前执行,并且如果再次运行应用程序,则可以返回不同的哈希码。

为了获得最佳性能,散列函数必须为所有输入生成随机分布。

您可能会为许多不相等的对象返回 0,尽管这不会破坏租户“如果两个对象不比较相等,则两个对象的 GetHashCode 方法不必返回不同的值”如果太多对象返回 0 那么你不会满足“为了获得最佳性能,散列函数必须为所有输入生成随机分布。”

此外,

覆盖 GetHashCode 的派生类也必须覆盖 Equals 以保证被认为相等的两个对象具有相同的哈希码;否则,Hashtable 类型可能无法正常工作。

因此,您还应该发布 Equals 的实现以确保 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;
于 2013-10-07T20:08:01.547 回答