April 24, 2009

How to test equality of objects of generic type in C#

Testing two objects for equality seems to be a very easy thing. If you try to write a generic method that does that, your first try might look like this:


public static bool AreEqual<T>(T param1, T param2)
{
return param1 == param2;
}

But it turns out that it doesn't compile:

Operator '==' cannot be applied to operands of type 'T' and 'T'

OK, next try. Why not use the IEquatable<T> interface? Value types implement it so you are not limited to reference types. It could look like this:


public static bool AreEqual<T>(T param1, T param2)
where T: IEquatable<T>
{
return param1.Equals(param2);
}

It compiles (yes! ;-)) and seems to work. But there are problems with it.

Firstly, of course, you will get an exception when param1 is null. In case you think this is easy to solve by testing for null stop reading here and try it yourself before reading on.

You cannot compare it to null as this only works for reference types. Of course instead of null we could use default(T) which returns null for reference types and 0 for value types. But then we again have the problem that the comparison (param1 == default(T)) won't compile. The same error as above...

The second problem is that we have to implement IEquatable<T> for all our classes even if we just want to use reference equality. Not a big deal but still a bit of an annoyance.

But it turns out that the solution to all this is again very simple:

public static bool AreEqual<T>(T param1, T param2)
{
return EqualityComparer<T>.Default.Equals(param1, param2);
}

The static property EqualityComparer<T>.Default returns the default equality comparer for the given type. When T implements IEquatable<T> it returns a comparer that uses that. If not, the default reference equality is used.

Exactly what we need. Not difficult, but you just have to know about it...
blog comments powered by Disqus