4

I need to override Equals() method for one of my types but it seems I have to also override GetHashCode() method.

I am not sure:

If I have type Animal and if I have 2 instances of Animal which are basically the same(equal)Cats; like:

Animal cat_01 = new Animal("Kitty", "Pink");
Animal cat_02 = new Animal("Kitty", "Pink");

Should I implement the GetHashedCode() to retirn same value for both cas_01 and cat_02 eventhough they represent different references in the memory?

Is it the way GetHashCode() shuold work?

Thanks

pencilCake
  • 51,323
  • 85
  • 226
  • 363
  • 2
    Basically your Animal class probably should _not_ override Equals, GetHashCode or `==`. If you do then also design it as immutable. Also see MattDavey's answer. – H H Sep 05 '11 at 12:38

3 Answers3

4

MSDN says:

If two objects compare as equal, the GetHashCode method for each object must return the same value.

So yes, GetHashCode should return the same value for both instances.

You can still use Object.ReferenceEquals if you want to see if they refer to the same object.

Botz3000
  • 39,020
  • 8
  • 103
  • 127
  • 2
    FYI for anyone who comes across this question in the future - this is not the right answer in all circumstances. Give some consideration in OO terms as to when your entities should be considered equal and when they should not. Considering objects always equal when they have similar properties is **often** a mistake. – MattDavey Sep 05 '11 at 12:44
  • 2
    My answer just answers the basic question: Should GetHashCode return the same value for two objects where Equals returns true? Whether overriding equals in this case makes sense, is another matter of course. – Botz3000 Sep 05 '11 at 12:49
3

I would disagree with the other answers.. Animal in this example is not a value object, it's perfectly feasable that two cats could have the same name & colour and be completely distinct entities. Logically you're saying "this cat and that cat have the same name and the same colour, therefore they are the same cat" - which is not necessarily true..

What I would suggest you do is leave Animal.Equals to the default implementation, and create a seperate IEqualityComparer implementation that returns true if the animals have the same name/colour.

public class AnimalNameColorComparer : IEqualityComparer<Animal>
{
    public bool Equals(Animal a, Animal b)
    {
        return a.Name == b.Name &&
               a.Color == b.Color
    }

    public int GetHashCode(Animal a)
    {
        return a.Name.GetHashCode() ^ a.Color.GetHashCode();
    }
}

Try to remember that there are many different ways to compare a cat, and one single "Equals" method is not enough :)

// Create two black cats called fluffy...
var cat1 = new Cat("Fluffy", "Black");
var cat2 = new Cat("Fluffy", "Black");

cat1.Equals(cat2) == false; // they are not the same cat!

var comparer = new AnimalNameColorComparer();

comparer.Equals(cat1, cat2) == true; // But they do have the same name & colour...
MattDavey
  • 8,897
  • 3
  • 31
  • 54
  • This question is specifically about implementing GetHashCode, which is a special requirement for keys used in dictionary type lookups. Equality is considered after generating the hashcode, if there are collisions. – Tim Lloyd Sep 05 '11 at 12:32
  • if you refer to a non-author user in a comment, you should quote their @username or they won't be notified. – Tim Lloyd Sep 05 '11 at 12:35
  • 3
    +1 for not answering the question but pointing out the design fault that prompted it. – H H Sep 05 '11 at 12:36
  • Back on topic - by overriding GetHashCode you cannot have two cats with the same name and colour in the dictionary, would that really be desired program behaviour? Leaving GetHashCode and Equals to their default implementation would be the correct thing to do in this case. – MattDavey Sep 05 '11 at 12:36
  • 1
    @Matt Yes you can have two cats with the same name and color in the dictionary, it's the keys they are stored under which cannot be the same. GetHashCode is called on the *key*. – Tim Lloyd Sep 05 '11 at 12:48
  • 2
    This is a good point BUT I think we can be fairly sure that asker's *actual* class is not `Animal`, so the (absolutely true) point that real-world animals are not uniquely identified by their name and colour doesn't necessarily apply. Note that the question text includes "which are basically the same" which *suggests* that for the actual class, equality of these two members *does* imply equality of identity. – AakashM Sep 05 '11 at 12:48
1

Depending on the design of the model, if it is value object (immutable) then the gethashcode should return a hashed value of all the fields, but on the other hand if it is a domain entity then it should have an identity and this identity should be used in comparison and gethashcode (two persons with the same name and age are not the same, if you have two cats with the same name that does not mean they are the same cat!).

check: http://moh-abed.com/2011/07/13/entities-and-value-objects/

Mohamed Abed
  • 5,025
  • 22
  • 31