Implementing the IEquatable of T interface for object equality with C# .NET

In this short post we’ll see a way how to make two custom objects equatable using the generic IEquatable interface. Consider the following object:

public class Person
{
	public int Id { get; set; }
	public string Name { get; set; }
	public int Age { get; set; }
}

The object superclass has an Equals method that we can test as follows:

Person personOne = new Person() { Age = 6, Name = "Eva", Id = 1 };
Person personTwo = new Person() { Age = 6, Name = "Eva", Id = 1 };
Console.WriteLine(personOne.Equals(personTwo));

This will obviously yield false as the Person objects are reference types. PersonOne and personTwo do not point to the same position in memory so they are deemed different.

Another problem with the Object.Equals method is that it’s not type safe. We can have a completely different object…

public class House
{
	public double Area { get; set; }
	public int NumberOfRooms { get; set; }
	public string Address { get; set; }
	public bool ForSale { get; set; }
	public DateTime DateBuilt { get; set; }
}

…and test equality with a Person:

Person personOne = new Person() { Age = 6, Name = "Eva", Id = 1 };
House house = new House()
{
	Address = "London",
	Area = 123.45,
	ForSale = false,
	NumberOfRooms = 4,
	DateBuilt = DateTime.UtcNow.AddYears(-2)
};
Console.WriteLine(personOne.Equals(house));

…the compiler won’t complain as Object.Equals accepts any object.

One way to implement equality is using the generic IEquatable interface which has only one method: Equals. We’ll say that two Person objects are equal if their IDs are equal:

public class Person : IEquatable<Person>
{
	public int Id { get; set; }
	public string Name { get; set; }
	public int Age { get; set; }

	public bool Equals(Person other)
	{
                if (other == null) return false;
		return Id == other.Id;
	}
}

The previous code…

Person personOne = new Person() { Age = 6, Name = "Eva", Id = 1 };
Person personTwo = new Person() { Age = 6, Name = "Eva", Id = 1 };
Console.WriteLine(personOne.Equals(personTwo));

…will now print true.

However, we still have a slight problem. It’ probably unlikely but it can happen that a Person will be declared as an object:

object personOne = new Person() { Age = 6, Name = "Eva", Id = 1 };
Person personTwo = new Person() { Age = 6, Name = "Eva", Id = 1 };
Console.WriteLine(personOne.Equals(personTwo));

The compiler will now call Object.Equals, not Person.Equals as we’re passing in an object type to the Equals method. Again, it returns false. As a solution we can override object.Equals in the Person class:

public override bool Equals(object obj)
{
	if (obj is Person)
	{
		Person p = (Person)obj;
		return Equals(p);
	}
	return false;
}

The previous example will now return true.

One last thing. If an object overrides Object.Equals it should also override GetHashCode which will return an integer. In our case we can just return the ID as our equality is based on IDs:

public override int GetHashCode()
{
	return Id;
}

View all various C# language feature related posts here.

About Andras Nemes
I'm a .NET/Java developer living and working in Stockholm, Sweden.

5 Responses to Implementing the IEquatable of T interface for object equality with C# .NET

  1. Interesting, but why do you say that it should over ride `GetHashCode` as well?

  2. Hey Andras.

    Concise as always.

    Just curious. What keeps the Equals override from being called infinitely recursively, when trying to equate to true?

    Keep up the good work.

    • Andras Nemes says:

      Hi Brent,

      Because we cast the object to Person within the overridden object.Equals method. We then call Person.Equals since we pass in the Person object ‘p’.

      //Andras

  3. Vikram says:

    the article is very concise, awesome and to the point. Thank you 🙂

Leave a comment

Elliot Balynn's Blog

A directory of wonderful thoughts

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT TUTORIALS WITH OPEN-SOURCE PROJECTS

Once Upon a Camayoc

Bite-size insight on Cyber Security for the not too technical.