简体   繁体   English

警告:“...覆盖Object.Equals(对象o)但不覆盖Object.GetHashCode()”

[英]Warning: “… overrides Object.Equals(object o) but does not override Object.GetHashCode()”

I overrode the Equals() of my class to compare ID values of type Guid. 我重写了我班级的Equals()来比较Guid类型的ID值。

Then Visual Studio warned: 然后Visual Studio警告:

... overrides Object.Equals(object o) but does not override Object.GetHashCode() ...重写Object.Equals(object o)但不覆盖Object.GetHashCode()

So I then also overrode its GetHashCode() like this: 所以我然后也像这样覆盖它的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();
    }
}

It seems to work. 它似乎工作。 Have I done this correctly? 我做得对吗? Remember Id is of type Guid. 记住Id是Guid类型。 Does it matter that my class is an Entity Framework object? 我的类是实体框架对象是否重要?

As others have said, the use of Reflection in Equals seems dodgy. 正如其他人所说的那样,在平等中使用反思似乎很狡猾。 Leaving that aside, let's concentrate on GetHashCode. 抛开这一点,让我们专注于GetHashCode。

The primary rule for GetHashCode that you must not violate is if two objects are equal then they must both have the same hash code . 您必须不违反GetHashCode的主要规则是, 如果两个对象相等,则它们必须具有相同的哈希码 Or, an equivalent way of saying that is if two objects have different hash codes then they must be unequal. 或者,相同的说法是, 如果两个对象具有不同的哈希码,那么它们必须是不相等的。 Your implementation looks good there. 你的实现看起来不错。

You are free to violate the converse. 你可以自由地违反反过来。 That is, if two objects have the same hash code then they are permitted to be equal or unequal, as you see fit. 也就是说,如果两个对象具有相同的哈希码,则允许它们相等或不相等,如您所见。

I am assuming that "Id" is an immutable property. 我假设“Id”是一个不可变的属性。 If "Id" can change over the lifetime of the object then you can have problems when putting the object in a hash table. 如果“Id”可以在对象的生命周期内更改,那么将对象放入哈希表时可能会出现问题。 Consider ensuring that only immutable properties are used in computing equality and hash code. 考虑确保在计算相等性和哈希码时仅使用不可变属性。

Your implementation looks good but the fact that you are asking the question indicates that you might not have a solid grasp of all the subtle factors that go into building an implementation of GetHashCode. 您的实现看起来不错,但您提出问题的事实表明您可能无法掌握构建GetHashCode实现的所有细微因素。 A good place to start is my article on the subject: 一个好的开始是我关于这个主题的文章:

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

It looks correct to me. 它对我来说是正确的。 Whenever I do something like this, I usually also implement IEquatable so that comparisons between variables of the same compile-time type will be a little more effecient. 每当我做这样的事情时,我通常也会实现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();
     }
} 

This structure also allows a more derived object with the same Id to compare as equal to a less derived object. 此结构还允许具有相同Id的更多派生对象进行比较,使其等于较少派生的对象。 If this is not the desired behavior, then you will have to also compare the types as you do in the question. 如果这不是所需的行为,那么您还必须像在问题中那样比较类型。

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

Since you're not dealing with a sealed class, I'd recommend against checking for class equality like this this.GetType() != obj.GetType() . 既然你没有处理一个密封的类,我建议不要像这样检查类的相等性this.GetType() != obj.GetType() Any sub-class of SomeClass should be able to participate in Equals also, so you might want to use this instead: SomeClass任何子类也应该能够参与Equals ,所以你可能想要使用它:

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

Traditionally Equals is implemented in such a way that two objects will only be "Equal" if they are exactly the same in every way. 传统上, Equals以这样的方式实现:如果两个对象在各方面都完全相同,那么它们将只是“等于”。 For example, if you have two objects that represent the same object in the database, but where one has a different Name property than the other, the objects aren't considered "Equal", and should avoid producing the same "Hashcode" if possible. 例如,如果您有两个对象代表数据库中的同一个对象,但是其中一个对象具有与另一个不同的Name属性,则对象不会被视为“Equal”,并且如果可能,应避免生成相同的“Hashcode” 。

It is better to err on the side of "not equal" than to risk calling two objects equal that aren't. 最好是在“不平等”方面犯错,而不是冒险调用两个不相等的对象。 This is why the default implementation for objects uses the memory location of the object itself: no two objects will ever be considered "equal" unless they are exactly the same object. 这就是对象的默认实现使用对象本身的内存位置的原因:除非它们是完全相同的对象,否则不会将两个对象视为“相等”。 So I'd say unless you want to write both GetHashCode and Equals in such a way that they check for equality of all their properties, you're better off not overriding either method. 所以我要说除非你想以这样的方式编写GetHashCodeEquals来检查它们所有属性的相等性,否则最好不要覆盖任何一种方法。

If you have a data structure (like a HashSet ) where you specifically want to determine equality based on the ID value, you can provide a specific IEqualityComparer implementation to that data structure. 如果您有一个数据结构(如HashSet ),您特别希望根据ID值确定相等性,则可以为该数据结构提供特定的IEqualityComparer实现。

You got excelent answers to your first question: 你得到了第一个问题的优秀答案:

Have I done it correctly? 我做得对吗?

I will answer your second question 我会回答你的第二个问题

Does it matter that my class is an Entity Framework object? 我的类是实体框架对象是否重要?

Yes it matters a lot. 是的,这很重要。 Entity framework uses HashSet a lot internally. 实体框架在内部使用了很多HashSet For example dynamic proxies use HashSet for representing collection navigation properties and EntityObject s use EntityCollection which in turn uses HashSet internally. 例如,动态代理使用HashSet表示集合导航属性,而EntityObject使用EntityCollection ,而EntityCollection又在内部使用HashSet

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

相关问题 为什么我收到此Resharper警告-不覆盖&#39;Object.Equals(object o)和&#39;Object.GetHashcode()&#39; - Why I am getting this Resharper warning - does not override 'Object.Equals(object o) and 'Object.GetHashcode()' C#运算符重载:Object.Equals(object o)和Object.GetHashCode() - C# operator overloading: Object.Equals(object o) & Object.GetHashCode() 警告:对象定义运算符 == 或运算符 != 但不会覆盖 Object.Equals(object o) - Warning: Object defines operator == or operator != but does not override Object.Equals(object o) Object.GetHashCode()的实现 - Implementation of Object.GetHashCode() 如何在重写GetHashCode()的类型上使用Object.GetHashCode() - How to use Object.GetHashCode() on a type that overrides GetHashCode() Object.GetHashCode - Object.GetHashCode 将Object.GetHashCode()转换为Guid - Converting Object.GetHashCode() to Guid 关于如何正确覆盖object.GetHashCode()的一般建议和指南 - General advice and guidelines on how to properly override object.GetHashCode() static Object.Equals方法,GetHashCode的默认实现和Dictionary类 - static Object.Equals method, default implementation of GetHashCode and the Dictionary class Object.GetHashCode()对引用或值是唯一的吗? - Is Object.GetHashCode() unique to a reference or a value?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM