警告:";..重写Object.Equals(Object o),但不重写Object.GetHashCode(

本文关键字:Object 重写 GetHashCode Equals quot 警告 | 更新日期: 2023-09-27 18:00:11

我重写类的Equals()以比较Guid类型的ID值。

然后Visual Studio发出警告:

覆盖Object.Equals(对象o),但是不覆盖Object.GetHashCode()

因此,我还重写了它的GetHashCode(),如下所示:

public partial class SomeClass
{
    public override bool Equals(Object obj)
    {
        //Check for null and compare run-time types.
        if (obj == null || this.GetType() != obj.GetType()) return false;
        return this.Id == ((SomeClass)obj).Id;
    }
    public override int GetHashCode()
    {
        return this.Id.GetHashCode();
    }
}

这似乎奏效了我做对了吗记住Id的类型为Guid我的类是实体框架对象有关系吗

警告:";..重写Object.Equals(Object o),但不重写Object.GetHashCode(

正如其他人所说,在Equals中使用反射似乎是不可靠的。抛开这些不谈,让我们集中讨论GetHashCode。

不能违反的GetHashCode的主要规则是如果两个对象相等,则它们必须具有相同的哈希代码。或者,一种等效的说法是如果两个对象有不同的哈希码,那么它们一定是不相等的您的实现看起来不错。

你可以违反相反的规定。也就是说,如果两个对象具有相同的哈希代码,则允许它们相等或不相等,正如您所认为的那样。

我假设"Id"是一个不可变的属性。如果"Id"可以在对象的生存期内更改,那么在将对象放入哈希表时可能会出现问题。考虑确保在计算等式和哈希代码时只使用不可变的属性。

您的实现看起来不错,但您提出这个问题的事实表明,您可能还没有完全掌握构建GetHashCode实现的所有微妙因素。一个好的开始是我的文章主题:

http://ericlippert.com/2011/02/28/guidelines-and-rules-for-gethashcode/

这对我来说是正确的。每当我做这样的事情时,我通常还会实现IEquatable,这样同一编译时类型的变量之间的比较就会更加有效。

public partial class SomeClass : IEquatable<SomeClass>
{
     public override bool Equals(Object obj)
     {
         return Equals(obj as SomeClass);
     }
     public bool Equals(SomeClass obj)
     {
         if (obj == null) 
             return false;
         return Id == obj.Id;
     }
     public override int GetHashCode()
     {
         return Id.GetHashCode();
     }
} 

此结构还允许具有相同Id的派生程度较高的对象与派生程度较低的对象进行比较。如果这不是想要的行为,那么你也必须像在问题中那样比较类型。

if (obj.GetType() != typeof(SomeClass)) return false;

传统上,Equals的实现方式是,只有两个对象在各个方面完全相同,它们才会"相等"。例如,如果数据库中有两个表示同一对象的对象,但其中一个具有与另一个不同的Name属性,则这些对象不被视为"相等",并且应尽可能避免生成相同的"哈希代码"。

与其冒险调用两个不相等的对象,不如选择"不相等"。这就是为什么对象的默认实现使用对象本身的内存位置:除非两个对象完全是同一个对象,否则任何两个对象都不会被视为"相等"。所以我想说,除非你想同时写GetHashCodeEquals,让它们检查所有属性的相等性,否则最好不要重写这两个方法。

如果您有一个数据结构(如HashSet),特别希望根据ID值确定相等性,则可以为该数据结构提供特定的IEqualityComparer实现。

由于您不是在处理密封类,我建议不要像this.GetType() != obj.GetType()那样检查类的相等性。SomeClass的任何子类也应该能够参与Equals,所以你可能想使用这个:

if (obj as SomeClass == null) return false;

您的第一个问题得到了极好的答案:

我做对了吗?

我会回答你的第二个问题

我的类是EntityFramework对象有关系吗?

是的,这很重要。实体框架内部大量使用HashSet。例如,动态代理使用HashSet来表示集合导航属性,而EntityObject使用EntityCollection,后者又在内部使用HashSet