Programming
Lambda Functions
Distinct Function
Coding Techniques
Software Development

Distinct() with lambda?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In LINQ, Distinct() does not take a lambda selector. That is the first thing to get clear. Distinct() removes duplicates using the element's equality rules, or an IEqualityComparer<T> that you provide. If you want "distinct by this property," the modern method is DistinctBy(...).

That distinction matters because many examples online blur together three different patterns: Distinct(), DistinctBy(...), and GroupBy(...). They solve related problems, but they are not interchangeable.

Know What Distinct() Actually Accepts

Plain Distinct() works when the type already has the equality behavior you want, or when you pass a custom comparer.

csharp
1var numbers = new[] { 1, 2, 2, 3, 3, 4 };
2var distinctNumbers = numbers.Distinct();
3
4foreach (var n in distinctNumbers)
5{
6    Console.WriteLine(n);
7}

There is no lambda overload here. If your data is a complex type and you want uniqueness based on one property, Distinct() alone is not enough.

Use DistinctBy(...) for a Key Selector

If you are on a modern .NET version that supports it, DistinctBy(...) is the direct answer when people ask for "Distinct with lambda."

csharp
1public record Product(int Id, string Name);
2
3var products = new List<Product>
4{
5    new(1, "Apple"),
6    new(1, "Apple duplicate"),
7    new(2, "Banana")
8};
9
10var distinctProducts = products.DistinctBy(p => p.Id);
11
12foreach (var product in distinctProducts)
13{
14    Console.WriteLine($"{product.Id} {product.Name}");
15}

The lambda p => p.Id is a key selector. It tells LINQ which value to use when deciding whether two items count as duplicates.

That is usually what developers really mean by "Distinct with lambda."

Use a Custom Comparer When DistinctBy Is Not Available

If you need to stay with plain Distinct(), provide an IEqualityComparer<T>.

csharp
1using System.Collections.Generic;
2
3public class ProductIdComparer : IEqualityComparer<Product>
4{
5    public bool Equals(Product? x, Product? y)
6    {
7        if (x is null || y is null) return x == y;
8        return x.Id == y.Id;
9    }
10
11    public int GetHashCode(Product obj)
12    {
13        return obj.Id.GetHashCode();
14    }
15}
16
17var distinctProducts = products.Distinct(new ProductIdComparer());

This is more verbose than DistinctBy(...), but it works everywhere that LINQ supports custom comparers.

Use GroupBy(...) as a Fallback Pattern

Another common fallback is GroupBy(...) followed by First():

csharp
var distinctProducts = products
    .GroupBy(p => p.Id)
    .Select(g => g.First());

This works, but it expresses a slightly heavier idea than necessary. If you only want unique items by key, DistinctBy(...) is usually clearer than building groups first.

Still, it is a useful pattern to know when you need more than the first element, such as counts or grouped inspection.

Common Pitfalls

The biggest mistake is assuming Distinct() itself has a lambda overload. It does not. If you write Distinct(x => x.Id), you are asking for an API that is not there.

Another common issue is using Distinct() on a custom class without defining equality behavior. In that case, reference equality may be used, and duplicates that look obvious to you may remain.

It is also easy to choose GroupBy(...) when DistinctBy(...) would be simpler and more direct.

One more subtle point is result preservation. DistinctBy(...) keeps the first element encountered for each key, so source ordering still affects which representative item survives.

Finally, remember that uniqueness depends on the key you pick. Distinct by Id and distinct by (Id, Name) are different operations with different results.

Summary

  • 'Distinct() does not accept a lambda key selector.'
  • Use DistinctBy(...) when you want uniqueness based on a property.
  • Use Distinct() with IEqualityComparer<T> when you need broader compatibility.
  • 'GroupBy(...).Select(g => g.First()) is a workable fallback.'
  • Be explicit about what "duplicate" means for your data.

Course illustration
Course illustration

All Rights Reserved.