Distinct by One Field in C#: How to Remove Duplicate Objects

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Problem: Distinct() Cannot Filter by Field

\n\n

Imagine: you have a list of clients, and there are duplicates by email. You write:

\n\n
var uniqueClients = clients.Distinct().ToList();
\n\n

And you are surprised to find that the duplicates are still there. Why? Because the standard Distinct() compares entire objects by reference (or by Equals, if you have overridden it). It doesn't know that for you, "uniqueness" means a unique Email, not a unique class instance.

\n\n

This question is one of the most popular on Stack Overflow regarding LINQ (over 500 thousand views). And today we will break down 3 working methods to solve this problem in C#. Let's go!

\n\n

Method 1. GroupBy + First (the classic)

\n\n

The simplest and most understandable method that does not require installing third-party libraries. The idea: group objects by the desired property, then take the first element from each group.

\n\n
var uniqueByEmail = clients\n    .GroupBy(c => c.Email)\n    .Select(g => g.First())\n    .ToList();
\n\n

How it works:

\n
    \n
  • GroupBy(c => c.Email) — splits the collection into groups where the key is the email.
  • \n
  • Select(g => g.First()) — takes the first object from each group.
  • \n
  • The remaining duplicates are discarded.
  • \n
\n\n

Pros:

\n
    \n
  • Works "out of the box" (only using System.Linq;).
  • \n
  • Intuitively understandable even for a beginner.
  • \n
  • Preserves the original order of elements (the first encountered object remains).
  • \n
\n\n

Cons:

\n
    \n
  • Slightly slower on large data (needs to create groups).
  • \n
  • The code is a bit more verbose than desired.
  • \n
\n\n

Method 2. MoreLinq and DistinctBy (elegance)

\n\n

If you are not afraid of third-party libraries, then MoreLinq offers the ideal DistinctBy method. It does exactly what you expect from Distinct — filters by property.

\n\n

Installation via NuGet:

\n
Install-Package MoreLinq
\n\n

Usage:

\n
using MoreLinq;\n\nvar uniqueByEmail = clients.DistinctBy(c => c.Email).ToList();
\n\n

One line — and it's done. Internally, DistinctBy uses a HashSet and works in O(n).

\n\n

Pros:

\n
    \n
  • Extremely concise and readable code.
  • \n
  • High performance.
  • \n
  • The library is well-tested (over 10 million downloads).
  • \n
\n\n

Cons:

\n
    \n
  • Need to add a dependency to the project.
  • \n
  • Not all teams allow third-party libraries.
  • \n
\n\n

Method 3. Custom IEqualityComparer (maximum control)

\n\n

This method is suitable when you don't want to pull in a library, but you want to reuse the comparison logic in multiple places. Create your own comparer:

\n\n
public class ClientEmailComparer : IEqualityComparer<Client>\n{\n    public bool Equals(Client x, Client y)\n    {\n        if (ReferenceEquals(x, y)) return true;\n        if (x is null || y is null) return false;\n        return x.Email == y.Email;\n    }\n\n    public int GetHashCode(Client obj)\n    {\n        return obj.Email?.GetHashCode() ?? 0;\n    }\n}
\n\n

Usage:

\n
var comparer = new ClientEmailComparer();\nvar uniqueByEmail = clients.Distinct(comparer).ToList();
\n\n

Pros:

\n
    \n
  • Full control over the comparison logic.
  • \n
  • The comparer can be reused in Contains, Except, Union, etc.
  • \n
  • No external libraries required.
  • \n
\n\n

Cons:

\n
    \n
  • Lot of boilerplate code.
  • \n

Blogs

Book Recommendations