Implementing the IEqualityComparer of T interface for object equality with C# .NET
October 20, 2017 Leave a comment
The generic IEqualityComparer of T provides you a way to indicate whether two custom objects are equal. We’ve looked at equality in a number of posts on this blog – see the link below if you’re curious – and IEqualityComparer fulfils a similar purpose though its usage is different.
Equality comparers are most often used to filter out duplicates from a collection.
Consider the following class:
public class Triangle
{
public double BaseSide { get; set; }
public double Height { get; set; }
public double Area
{
get
{
return (BaseSide * Height) / 2;
}
}
}
Let’s say that two triangles are equal if their areas are the same. IEqualityComparer comes with two methods to be implemented: Equals and GetHashCode. GetHashCode returns an integer and two objects that are equal should return the same value. Here’s an IEqualityComparer implementation:
public class TriangleAreaEqualityComparer : IEqualityComparer<Triangle>
{
public bool Equals(Triangle x, Triangle y)
{
return x.Area == y.Area;
}
public int GetHashCode(Triangle obj)
{
return obj.Area.GetHashCode();
}
}
Let’s build a list of Triangle objects:
Triangle t1 = new Triangle()
{
BaseSide = 2,
Height = 2
};
Triangle t2 = new Triangle()
{
BaseSide = 2,
Height = 4
};
Triangle t3 = new Triangle()
{
BaseSide = 4,
Height = 2
};
Triangle t4 = new Triangle()
{
BaseSide = 3,
Height = 3
};
Triangle t5 = new Triangle()
{
BaseSide = 7,
Height = 5
};
Triangle t6 = new Triangle()
{
BaseSide = 5,
Height = 7
};
Triangle t7 = new Triangle()
{
BaseSide = 2,
Height = 2
};
Triangle t8 = new Triangle()
{
BaseSide = 8,
Height = 4
};
List<Triangle> triangles = new List<Triangle>();
triangles.Add(t1);
triangles.Add(t2);
triangles.Add(t3);
triangles.Add(t4);
triangles.Add(t5);
triangles.Add(t6);
triangles.Add(t7);
triangles.Add(t8);
Now we want to find the unique triangles by area. The Distinct LINQ operator is very useful as it also accepts an IEqualityComparer object:
List<Triangle> uniqueTriangles = triangles.Distinct(new TriangleAreaEqualityComparer()).ToList();
uniqueTriangles will include 5 of the original 8 triangles.
Instead of implementing IEqualityComparer you can derive from the EqualityComparer base class which implements the generic IEqualityComparer of T and the non-generic IEqualityComparer interface. The implementation is very similar to the one above:
public class TriangleAreaEqualityComparer : EqualityComparer<Triangle>
{
public override bool Equals(Triangle x, Triangle y)
{
return x.Area == y.Area;
}
public override int GetHashCode(Triangle obj)
{
return obj.Area.GetHashCode();
}
}
You can go with the above solution if you want to make your code available to old .NET clients that cannot handle generics.
View all various C# language feature related posts here.