LINQ: Enhancing Distinct With The PredicateEqualityComparer
Posted
by Paulo Morgado
on ASP.net Weblogs
See other posts from ASP.net Weblogs
or by Paulo Morgado
Published on Thu, 08 Apr 2010 01:18:04 GMT
Indexed on
2010/04/08
1:23 UTC
Read the original article
Hit count: 541
Today I was writing a LINQ query and I needed to select distinct values based on a comparison criteria.
Fortunately, LINQ’s Distinct method allows an equality comparer to be supplied, but, unfortunately, sometimes, this means having to write custom equality comparer.
Because I was going to need more than one equality comparer for this set of tools I was building, I decided to build a generic equality comparer that would just take a custom predicate. Something like this:
public class PredicateEqualityComparer<T> : EqualityComparer<T> { private Func<T, T, bool> predicate; public PredicateEqualityComparer(Func<T, T, bool> predicate) : base() { this.predicate = predicate; } public override bool Equals(T x, T y) { if (x != null) { return ((y != null) && this.predicate(x, y)); } if (y != null) { return false; } return true; } public override int GetHashCode(T obj) { if (obj == null) { return 0; } return obj.GetHashCode(); } }
Now I can write code like this:
.Distinct(new PredicateEqualityComparer<Item>((x, y) => x.Field == y.Field))
But I felt that I’d lost all conciseness and expressiveness of LINQ and it doesn’t support anonymous types. So I came up with another Distinct extension method:
public static IEnumerable<TSource> Distinct<TSource>(this IEnumerable<TSource> source, Func<TSource, TSource, bool> predicate) { return source.Distinct(new PredicateEqualityComparer<TSource>(predicate)); }
And the query is now written like this:
.Distinct((x, y) => x.Field == y.Field)
Looks a lot better, doesn’t it?
© ASP.net Weblogs or respective owner