简体   繁体   English

C#这是实现GetHashCode的不好方法吗?

[英]C# Is this a bad way to implement GetHashCode?

I'm trying to implement GetHashCode for an object that I have overridden Equals on. 我正在尝试为覆盖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();
}

Is this a reasonable way to do it, or is it likely to cause collisions with base.GetHashCode()? 这是一种合理的方法,还是可能导致与base.GetHashCode()的冲突?

EDIT: I appreciate the solutions given thus far, but the same question remains. 编辑:我感谢到目前为止给出的解决方案,但仍然存在相同的问题。 If I do not implement a complete GetHashCode and rely on some other implementation, either base.GetHashCode(), or Guid.GetHashCode(), is there a chance for hash code collisions with the hardcoded 0 value? 如果我没有实现完整的GetHashCode并依赖于base.GetHashCode()或Guid.GetHashCode()的其他实现,那么哈希代码是否有可能与硬编码0值冲突? And if so, is there a simple way to avoid it? 如果是这样,有没有一种简单的方法可以避免这种情况?

Based on your Equals method, what you consider to truly be the "identity" of an object is the value of SomeProperty.ID , with some additional handling of null values/properties/etc. 根据您的Equals方法,您认为真正是对象的“身份”的是SomeProperty.ID的值,还需要对null值/ properties / etc进行一些其他处理。

That should be reflected in the hash code as well. 这也应该反映在哈希码中。

You should start out handing all of those edge cases, as you do in your Equals method. 您应该像处理Equals方法一样开始处理所有这些极端情况。 It seems like you kind sorta went down this path, but didn't quite get there. 好像您有点儿走这条路,但还没到那儿。 If the object's SomeProperty is null OR it IsDefault then it doesn't have an ID, and to us, all such objects are "the same" and should have the same hash code. 如果对象的SomeProperty为null IsDefault则它没有ID,对我们来说,所有此类对象都是“相同的”,并且应具有相同的哈希码。

After that though, rather than leveraging the base class' hash code, you need to actually base the hash on the ID property, which is what your Equals method does next. 不过,在那之后,您无需真正利用基类的哈希码,而需要将哈希实际基于ID属性,这是您的Equals方法接下来要做的。 Since ID is an Guid we know it has a sensible GetHashCode implementation, so we can just leverage that, and then you're done: 由于IDGuid我们知道它具有明智的GetHashCode实现,因此我们可以利用它,然后完成了:

public override int GetHashCode()
{
    if (SomeProperty == null || SomeProperty.IsDefault)
        return 0;
    else 
        return SomeProperty.ID.GetHashCode();
}

Or, if it's easier for you to read, we could reverse the logic. 或者,如果您更容易阅读,我们可以颠倒逻辑。 Rather than saying, "If this doesn't have an ID, return zero, else return the ID's hash code" we can say, "If we have an ID, return it's hash code, else just return zero: 与其说“如果没有ID,则返回零,否则返回ID的哈希码”,我们可以说:“如果有ID,则返回其哈希码,否则仅返回零:

public override int GetHashCode()
{
    if (SomeProperty != null && !SomeProperty.IsDefault)
        return SomeProperty.ID.GetHashCode();
    else 
        return 0;
}

personally I think the first has a bit more symmetry with your Equals method, but the second seems a bit closer to what you were trying to do, which is why I'm throwing it up there. 我个人认为第一个与您的Equals方法具有更多的对称性,但是第二个似乎与您尝试执行的操作更加接近,这就是为什么我将它扔在那里的原因。

That is not a good solution. 那不是一个好的解决方案。 The documentation shows 文档显示

A hash function must have the following properties: 哈希函数必须具有以下属性:

If two objects compare as equal, the GetHashCode method for each object must return the same value. 如果两个对象比较相等,则每个对象的GetHashCode方法必须返回相同的值。 However, if two objects do not compare as equal, the GetHashCode methods for the two object do not have to return different values. 但是,如果两个对象的比较不相等,则两个对象的GetHashCode方法不必返回不同的值。

The GetHashCode method for an object must consistently return the same hash code as long as there is no modification to the object state that determines the return value of the object's Equals method. 只要没有修改确定对象的Equals方法返回值的对象状态,对象的GetHashCode方法就必须始终返回相同的哈希码。 Note that this is true only for the current execution of an application, and that a different hash code can be returned if the application is run again. 请注意,这仅适用于当前执行的应用程序,并且如果再次运行该应用程序,则可以返回不同的哈希码。

For the best performance, a hash function must generate a random distribution for all input. 为了获得最佳性能,哈希函数必须为所有输入生成随机分布。

You are presumably returning 0 for many unequal objects and although this does not break the tenant "if two objects do not compare as equal, the GetHashCode methods for the two object do not have to return different values" if too many objects return 0 then you will not fulfill "For the best performance, a hash function must generate a random distribution for all input." 您可能会为许多不相等的对象返回0,尽管这不会破坏租户“如果两个对象的比较不相等,则两个对象的GetHashCode方法不必返回不同的值”,如果太多的对象返回0,则您不会满足“为获得最佳性能,散列函数必须为所有输入生成随机分布。”

In addition, 此外,

Derived classes that override GetHashCode must also override Equals to guarantee that two objects considered equal have the same hash code; 重写GetHashCode的派生类也必须重写Equals,以确保被认为相等的两个对象具有相同的哈希码。 otherwise, the Hashtable type might not work correctly. 否则,哈希表类型可能无法正常工作。

Therefore, you're implementation of Equals should also be posted to make sure that the GetHashCode is valid. 因此,还应发布您正在执行的Equals,以确保GetHashCode有效。

I would suggest updating it to 我建议将其更新为

public override int GetHashCode()
{
    if (SomeProperty == null || SomeProperty.IsDefault)
        return base.GetHashCode() ;
    else return SomeProperty.ID.GetHashCode();
}

Also, for a good discussion of the GetHashCode implemention you could look at this post 另外,为了更好地讨论GetHashCode实现,您可以查看这篇文章

In addition in your Equals if the SomeProperty==null in both objects you are returning false , is that intentional? 另外,在相等中,如果两个对象中的SomeProperty==null都返回false ,那是故意的吗?

or did you mean 还是你的意思

if (myobject.SomeProperty == null && SomeProperty == null)
    return true;
if (myobject.SomeProperty == null || SomeProperty == null)
    return false;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM