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.