我正在尝试为我已覆盖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值发生哈希码冲突?如果是这样,有没有一种简单的方法可以避免它?答案 0 :(得分:3)
根据您的Equals
方法,您认为真正属于对象的“身份”的是SomeProperty.ID
的值,还有一些额外的空值/属性等处理。
这也应该反映在哈希码中。
您应该像处理Equals
方法一样开始处理所有这些边缘情况。看起来好像你走了这条道路,但并没有完全达到目的。如果对象的SomeProperty
为空或它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
方法相比更加对称,但第二种方法似乎更接近你想要做的事情,这就是为什么我把它扔到那里。
答案 1 :(得分:1)
这不是一个好的解决方案。 documentation显示
哈希函数必须具有以下属性:
如果两个对象比较相等,则每个对象的GetHashCode方法 对象必须返回相同的值。但是,如果两个对象没有 比较相同,两个对象的GetHashCode方法不相同 必须返回不同的值。
对象的GetHashCode方法必须始终返回相同的值 哈希码只要没有对象状态的修改即可 确定对象的Equals方法的返回值。注意 这仅适用于当前执行的应用程序,并且 如果运行应用程序,则可以返回不同的哈希代码 试。
为获得最佳性能,哈希函数必须生成随机数 所有输入的分配。
对于许多不相等的对象,您可能会返回0,尽管这不会破坏租户“如果两个对象不相等,则两个对象的GetHashCode方法不必返回不同的值”如果太多对象返回0然后你将不会满足“为了获得最佳性能,哈希函数必须为所有输入生成随机分布。”
此外,
覆盖GetHashCode的派生类也必须覆盖等于 保证两个被认为相等的对象具有相同的哈希码; 否则,Hashtable类型可能无法正常工作。
因此,您也应该发布Equals的实现,以确保GetHashCode有效。
我建议将其更新为
public override int GetHashCode()
{
if (SomeProperty == null || SomeProperty.IsDefault)
return base.GetHashCode() ;
else return SomeProperty.ID.GetHashCode();
}
此外,有关GetHashCode实现的详细讨论,您可以查看此post
此外,如果您要返回SomeProperty==null
的两个对象中的false
,那么您的等号是否有意?
或者你的意思是
if (myobject.SomeProperty == null && SomeProperty == null)
return true;
if (myobject.SomeProperty == null || SomeProperty == null)
return false;