LINQ
Programming
.NET
C#
Distinct() Method

LINQ's Distinct() on a particular property

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Distinct() removes duplicate elements based on the equality of the element type itself. When you want uniqueness based on only one property, the cleanest solution depends on your .NET version: modern code usually uses DistinctBy, while older code falls back to GroupBy or a custom comparer.

Why Plain Distinct() Is Not Enough

Given a class like this:

csharp
1public class Employee
2{
3    public int Id { get; set; }
4    public string Name { get; set; } = "";
5}

calling Distinct() on a list of Employee objects does not magically know that Id is the property you care about.

csharp
1var employees = new List<Employee>
2{
3    new Employee { Id = 1, Name = "Alice" },
4    new Employee { Id = 2, Name = "Bob" },
5    new Employee { Id = 1, Name = "Alicia" }
6};
7
8var result = employees.Distinct().ToList();

Unless Employee overrides equality appropriately, those objects are treated as different instances.

Modern Solution: DistinctBy

If you are on modern .NET, DistinctBy is the most direct answer.

csharp
1using System;
2using System.Collections.Generic;
3using System.Linq;
4
5var employees = new List<Employee>
6{
7    new Employee { Id = 1, Name = "Alice" },
8    new Employee { Id = 2, Name = "Bob" },
9    new Employee { Id = 1, Name = "Alicia" }
10};
11
12var distinct = employees.DistinctBy(e => e.Id).ToList();
13
14foreach (var employee in distinct)
15{
16    Console.WriteLine($"{employee.Id} - {employee.Name}");
17}

This keeps the first element encountered for each distinct key value.

Older Fallback: GroupBy

If DistinctBy is unavailable, GroupBy is a readable fallback.

csharp
1var distinct = employees
2    .GroupBy(e => e.Id)
3    .Select(group => group.First())
4    .ToList();

The effect is similar: group by the property, then choose one representative from each group.

This is often simpler than writing a whole comparer when you only need the logic in one place.

Custom Comparer for Reuse

If the same distinct-by-property rule appears throughout the codebase, a custom IEqualityComparer<T> can be worth the extra code.

csharp
1using System.Collections.Generic;
2
3public class EmployeeIdComparer : IEqualityComparer<Employee>
4{
5    public bool Equals(Employee? x, Employee? y)
6    {
7        if (ReferenceEquals(x, y)) return true;
8        if (x is null || y is null) return false;
9        return x.Id == y.Id;
10    }
11
12    public int GetHashCode(Employee obj)
13    {
14        return obj.Id.GetHashCode();
15    }
16}

Then:

csharp
var distinct = employees.Distinct(new EmployeeIdComparer()).ToList();

This is useful when the equality rule is part of the domain and should be reused explicitly.

Do Not Override Equality Casually

You could override Equals and GetHashCode on the entity itself, but that changes equality for the whole application. That is only appropriate when the property truly defines the object's identity everywhere.

If Employee.Id is a database identity and that is your domain-wide notion of equality, overriding may be reasonable. If not, use DistinctBy, GroupBy, or a comparer instead of changing global object behavior.

Which Duplicate Survives

One subtle point is that property-based distinct operations typically keep the first item encountered for each key. That means order matters.

If you want "the newest record for each Id" rather than "the first record for each Id," sort first or choose the right group representative:

csharp
1var latestPerId = employees
2    .OrderByDescending(e => e.Name)
3    .DistinctBy(e => e.Id)
4    .ToList();

The property selector defines uniqueness, but the input order often determines which item is preserved.

Common Pitfalls

The biggest mistake is assuming Distinct() can infer which property should define equality. It cannot; it only knows about element equality.

Another issue is overriding Equals and GetHashCode just to satisfy one query. That can create surprising behavior everywhere else in the application.

Developers also forget that property-based distinct keeps one representative, not a merged record. If duplicates carry different non-key data, be deliberate about which one survives.

Finally, if DistinctBy is unavailable in your target framework, do not force awkward workarounds. GroupBy(...).Select(g => g.First()) is perfectly serviceable.

Summary

  • Plain Distinct() uses element equality, not a chosen property selector.
  • 'DistinctBy is the cleanest modern way to remove duplicates by one property.'
  • 'GroupBy(...).Select(g => g.First()) is a good fallback on older frameworks.'
  • Use a custom comparer when the rule should be reused across the codebase.
  • Be explicit about which duplicate record you want to keep.

Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.