C# Basics: Why We Override Equals Method

You may have come across the following questions:

  • Why override the Equals method?
  • How to determine whether two objects are equal?
  • How to determine whether two objects are identical?

To get an answer to all those questions, let us consider a Product class as listed next:

  1. class Product  
  2. {  
  3.    public int Price { getset; }  
  4.    public string Name { getset; }  
  5.   
  6. }  
We are creating two instances of the Product class, foo and loo. The foo is assigned to loo. Both objects are pointing to the same reference, hence we will get true as the expected output for all the Equals.
  1. Product foo = new Product {Price = 10,Name= "foo"};  
  2. Product loo = new Product();  
  3. loo = foo;   
  4. var valueEqual = foo.Equals(loo);  
  5. Console.WriteLine(valueEqual);   
  6.   
  7. var objRefEqual= Object.ReferenceEquals(foo, loo);  
  8. Console.WriteLine(objRefEqual);  
  9.   
  10. var objEqual = Object.Equals(foo,loo);   
  11. Console.WriteLine(objEqual);  
  12. Console.ReadKey(true);  
The expected output is:

output

Now let us proceed and modify the instances as listed next:
  1. Product foo = new Product {Price = 10,Name= "foo"};  
  2. Product loo = new Product();  
  3. loo.Price = 10;  
  4. loo.Name = "foo";  
  5. var valueEqual = foo.Equals(loo);  
  6. Console.WriteLine(valueEqual);   
  7.   
  8. var objRefEqual= Object.ReferenceEquals(foo, loo);  
  9. Console.WriteLine(objRefEqual);  
  10.   
  11. var objEqual = Object.Equals(foo,loo);   
  12. Console.WriteLine(objEqual);  
  13. Console.ReadKey(true);  
This time you will get output as false for all the three Equals method.

Equals method

However if you closely observe, the value of both of the properties of both objects are exactly the same. The Price and the Name properties are set to 100 and foo respectively. But still we are getting Equals returns false for the foo and the loo object.

We can observe that, even though the properties values are the same Equals returns false. Essentially, when arguments are referring to different objects Equals won't check for the values and always returns false. We can say that by default Equals check for identitical objects rather than equal objects.

Understanding Internal

To understand this behavior, let us examine the System.Object class. It contains:  
  • One virtual Equals method.

  • One static Equals method. This takes two arguments. It returns true if they are identical otherwise false.

  • One static ReferenceEquals method. This takes two arguments. Returns true if both arguments are the same instance otherwise false.

Clearly the CLR Equals method does not check for the values, when the arguments refer to different objects. So by default it checks for the Object Identity rather than Object Equality.

Why to override Equals()

We may come across the requirement to check for object equality. To check whether both objects contain the same property value or not. This can be done by overriding the Equals method. We can override the Equals method as listed next:

  1. class Product  
  2. {  
  3.     public int Price { getset; }  
  4.     public string Name { getset; }  
  5.     public override bool Equals(object obj)  
  6.     {  
  7.        if (obj == null)  
  8.             return false;  
  9.         if (this.GetType() != obj.GetType()) return false;  
  10.   
  11.         Product p = (Product)obj;  
  12.         return (this.Price == p.Price) && (this.Name == p.Name);  
  13.     }          
  14. }  
When overriding the Equals method, you should consider the following: 
  • If an object argument is null, return false.

  • If the type of an object argument is different than the type of this, return false.

  • If the object argument is neither null nor its type is different then check for the values of the instance fields. If they are equal return true else return false.

We have overridden the Equals method, now if you compare the objects that are listed next, you will find that Equals returns true if Objects are equal whereas ReferenceEquals returns false when objects are different.

  1. Product foo = new Product {Price = 10,Name= "foo"};  
  2. Product loo = new Product();  
  3. loo.Price = 10;  
  4. loo.Name = "foo";  
  5. var valueEqual = foo.Equals(loo);  
  6. Console.WriteLine(valueEqual);   
  7.   
  8. var objRefEqual= Object.ReferenceEquals(foo, loo);  
  9. Console.WriteLine(objRefEqual);  
  10.   
  11. var objEqual = Object.Equals(foo,loo);   
  12. Console.WriteLine(objEqual);  
  13. Console.ReadKey(true);  
You will get the expected output true, false and true.

expected output true

Summary

We started with the question, why override the Equals method? We learned that by default the System.Object Equals method does not check for the equality of the objects. It checks only for the object's identity. To check for object equality, we override the Equals method.

 

Next Recommended Readings