There is this excelent question and answer about this topic: Do I HAVE to override GetHashCode and Equals in new Classes?
As it mentions:
you only need to override them if you need value equality semantics. The System.Object implementation isn't 'bad', it just only does a reference check (which is all an implementation at that level can do).
In short: If you need some sort of value based equality (equality based on properties of the class), then yes, override away. Otherwise, it should be more than fine already.
Let's suppose I have a class User:
public class User: IEquatable<User>
{
    private readonly string _firstName;
    private readonly string _lastName;
    private readonly string _address;
    public User (string firstName, string lastName, string address)
    {       
        this._firstName = firstName;
        this._lastName = lastName;
        this._address = address;
    }
    public FirstName {get; private set;}
    public LastName {get; private set;}
    public Address {get; private set;}
    //should I need to override this?
    public override bool Equals(object right)
    {
        if (object.ReferenceEquals(right, null))
            return false;
        if (object.ReferenceEquals(this, right))
            return true;
        if (this.GetType() != right.GetType())
            return false;
        return this.Equals(right as User);
    }
    #region IEquatable<User> Members
    public bool Equals(User user)
    {
        bool isEqual = (this._firstName != null && this._firstName.Equals(user.FirstName, StringComparison.InvariantCultureIgnoreCase)) || 
                      (this._lastName != null && this._lastName.Equals(user.LastName, StringComparison.InvariantCultureIgnoreCase)) ||
                      (this._address != null && this._address.Equals(user.Address, StringComparison.InvariantCultureIgnoreCase)) ||
                      (this._firstName == null && this._lastName == null && this._address == null);
        return isEqual; 
    }
    #endregion
}
User user1 = new User("John", "Wayne", "Collins Avenue");
User user2 = new User("John", "Wayne", "Collins Avenue");
//if I don't override these methods, reference equals will be:
user1 == user2 // false
//if I override GetHashCode and Equals methods, then:
user1 == user2 //true
IList<User> usersList1 = new List<User>();
IList<User> usersList2 = new List<User>();
usersList1.Add(user1);
usersList2.Add(user2);
IList<User> finalUsersList = usersList1.Union(usersList2);
//if I don't override these methods, count will be:
finalUsersList.Count() // 2
//if I do override these methods, count will be:
finalUsersList.Count() // 1 
Is it right?
- The first Equals override method commented is required?
- In this case, which class members should I include in the GetHashCode override? All the members involved in the Equals method? - public override int GetHashCode() { unchecked { // Hash -> primes int hash = 17; hash = hash * 23 + FirstName.GetHashCode(); hash = hash * 23 + LastName.GetHashCode(); hash = hash * 23 + Address.GetHashCode(); return hash; } }
What happens if I only use FirstName for example?
 
     
     
    