If you've ever wanted to filter a collection for a distinct result you probably know about the extension-method .Distinct
in LINQ. It can be useful on simple data structures containing easily comparable objects, like I collection of strings
or ints
, but for more complex scenarios you need to pass in a IEqualityComparer
. This is not very convenient.
More convenient would be to able to pass in a Lambda-expression, specifying what field you want to do the distinction by, like this:
var distinctItems = items.Distinct(x => x.Id);
To do this, you can add the following extension-methods to your projects:
public static IQueryable<TSource> Distinct<TSource>(
this IQueryable<TSource> source, Expression<Func<TSource, object>> predicate)
{
// TODO: Null-check arguments
return from item in source.GroupBy(predicate) select item.First();
}
public static IEnumerable<TSource> Distinct<TSource>(
this IEnumerable<TSource> source, Func<TSource, object> predicate)
{
// TODO: Null-check arguments
return from item in source.GroupBy(predicate) select item.First();
}
The extension-method using IQueryable<T>
works with ORMs like Entity Framework, while IEnumerable<T>
works with all types of collections, in-memory or otherwise, depending on implementation.
Warning: Avoid using this with EF Core version 1.x or 2.0, since the .GroupBy
-execution is always made in-memory. So you might get the whole content of your database loaded into memory. Only use it with EF Core 2.1 and above in production-scenarios.