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.

Advertisements

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 Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

ultimatemindsettoday

A great WordPress.com site

Elliot Balynn's Blog

A directory of wonderful thoughts

Robin Sedlaczek's Blog

Developer on Microsoft Technologies

HarsH ReaLiTy

A Good Blog is Hard to Find

Softwarearchitektur in der Praxis

Wissenswertes zu Webentwicklung, Domain-Driven Design und Microservices

the software architecture

thoughts, ideas, diagrams,enterprise code, design pattern , solution designs

Technology Talks

on Microsoft technologies, Web, Android and others

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

Anything around ASP.NET MVC,WEB API, WCF, Entity Framework & AngularJS

Cyber Matters

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

Guru N Guns's

OneSolution To dOTnET.

Johnny Zraiby

Measuring programming progress by lines of code is like measuring aircraft building progress by weight.

%d bloggers like this: