sebnilsson.com | Liquid Development Is What I Do
Seb Nilsson

LINQ Distinct-Method using Lambda Expression

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.