LINQ Set Operations in C# Explained
Set operations in LINQ enable developers to manipulate and compare
collections using principles of mathematical set theory. This article
breaks down the four fundamental LINQ set operators in
C#—Distinct, Union, Intersect,
and Except. You will learn how each operator functions, how
duplicates are handled, and how to apply them effectively to both
primitive data types and custom objects in your applications.
Understanding LINQ Set Operations
LINQ set operations evaluate collection elements based on equality.
By default, primitive types (like int or
string) are evaluated by value, while reference types are
evaluated by reference unless IEquatable<T> is
implemented or a custom IEqualityComparer<T> is
provided.
1. Distinct
The Distinct operator removes duplicate elements from a
sequence, returning an unordered collection of unique values.
List<int> numbers = new() { 1, 2, 2, 3, 4, 4, 5 };
IEnumerable<int> uniqueNumbers = numbers.Distinct();
// Output: 1, 2, 3, 4, 5Starting in .NET 6, you can also use DistinctBy to
filter objects based on a specific property without needing a custom
equality comparer:
var uniqueUsers = users.DistinctBy(u => u.Email);2. Union
The Union operator combines two collections into a
single collection and automatically excludes duplicate elements. This
differs from Concat, which joins collections without
removing duplicates.
List<int> setA = new() { 1, 2, 3 };
List<int> setB = new() { 3, 4, 5 };
IEnumerable<int> result = setA.Union(setB);
// Output: 1, 2, 3, 4, 5Like Distinct, .NET 6 introduced UnionBy,
allowing you to combine two collections based on a specific key
selector.
3. Intersect
The Intersect operator returns only the elements that
exist in both source collections, discarding any items unique to either
collection.
List<string> groupA = new() { "Alice", "Bob", "Charlie" };
List<string> groupB = new() { "Bob", "Charlie", "David" };
IEnumerable<string> commonNames = groupA.Intersect(groupB);
// Output: Bob, CharlieUse IntersectBy when comparing complex collections based
on a key property rather than the entire object.
4. Except
The Except operator produces the set difference of two
collections. It returns all elements from the first collection that do
not appear in the second collection.
List<int> allTasks = new() { 1, 2, 3, 4, 5 };
List<int> completedTasks = new() { 2, 4 };
IEnumerable<int> pendingTasks = allTasks.Except(completedTasks);
// Output: 1, 3, 5Note that the order of collections matters. Calling
setA.Except(setB) produces different results than
setB.Except(setA).
Summary of Set Operators
| Operator | Purpose | Duplicate Handling |
|---|---|---|
Distinct |
Filters out duplicate values from a single collection | Returns only unique values |
Union |
Combines two collections | Excludes duplicate values |
Intersect |
Finds shared values present in both collections | Excludes duplicates in the result |
Except |
Finds values in collection A that are absent from collection B | Excludes duplicates in the result |