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?