C#
IEnumerable
Intersect method
list operations
programming tutorial

Intersection of multiple lists with IEnumerable.Intersect

Master System Design with Codemia

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

Introduction

Enumerable.Intersect is the standard LINQ tool for finding values that appear in more than one sequence. For two lists, the call is direct. For many lists, the usual solution is to chain Intersect calls or reduce a collection of lists with Aggregate.

How Intersect Behaves

The most important thing to remember is that Intersect uses set semantics. It returns distinct common values, not duplicate counts.

csharp
1using System;
2using System.Collections.Generic;
3using System.Linq;
4
5var a = new List<int> { 1, 2, 3, 4, 4 };
6var b = new List<int> { 2, 4, 6, 4 };
7
8var common = a.Intersect(b).ToList();
9Console.WriteLine(string.Join(", ", common));

Output:

text
2, 4

Notice that 4 appears more than once in the inputs but only once in the result.

Intersect More Than Two Lists

For a small fixed number of lists, chaining is easy to read.

csharp
1using System;
2using System.Collections.Generic;
3using System.Linq;
4
5var a = new List<int> { 1, 2, 3, 4 };
6var b = new List<int> { 2, 4, 6 };
7var c = new List<int> { 0, 2, 4, 8 };
8
9var common = a.Intersect(b).Intersect(c).ToList();
10Console.WriteLine(string.Join(", ", common));

That works well when the number of sequences is known and small.

Use Aggregate for a Dynamic Number of Lists

If the number of lists is only known at runtime, Aggregate is cleaner than writing a manual chain.

csharp
1using System;
2using System.Collections.Generic;
3using System.Linq;
4
5var groups = new List<List<string>>
6{
7    new() { "api", "web", "worker" },
8    new() { "web", "worker", "batch" },
9    new() { "worker", "web", "mobile" }
10};
11
12var intersection = groups
13    .Skip(1)
14    .Aggregate(groups.First().AsEnumerable(), (current, next) => current.Intersect(next))
15    .ToList();
16
17Console.WriteLine(string.Join(", ", intersection));

This keeps the first list as the initial candidate set, then removes anything not present in each later list.

If the outer collection may be empty, guard that case first so First() does not throw.

Equality Matters for Custom Types

For primitive types, default equality is usually fine. For custom objects, you often need an IEqualityComparer<T> so LINQ knows what it means for two items to be the same.

csharp
1using System;
2using System.Collections.Generic;
3using System.Linq;
4
5public record User(int Id, string Name);
6
7public class UserIdComparer : IEqualityComparer<User>
8{
9    public bool Equals(User? x, User? y) => x?.Id == y?.Id;
10    public int GetHashCode(User obj) => obj.Id.GetHashCode();
11}
12
13var first = new[] { new User(1, "Ana"), new User(2, "Ben") };
14var second = new[] { new User(2, "Benny"), new User(3, "Cara") };
15
16var common = first.Intersect(second, new UserIdComparer()).ToList();
17Console.WriteLine(common.Count);

Without a comparer, separate object instances that represent the same logical entity may not intersect the way you expect.

Deferred Execution and Materialization

Intersect is lazily evaluated. The work happens when you enumerate the result, not when you write the query. That is usually helpful, but if you need to iterate the intersection multiple times, materialize it with ToList() or ToHashSet().

The result order follows the encounter order of the first sequence for matching distinct elements. If you need sorted output, apply OrderBy explicitly afterward.

When Intersect Is Not the Right Tool

If you need duplicate-sensitive multiset behavior, Intersect is not the right abstraction. It answers "which values appear in all sequences," not "how many times does each value appear across the sequences."

That distinction matters in inventory, counting, and frequency-driven workflows.

Common Pitfalls

A common mistake is expecting duplicates to survive the intersection. Intersect deliberately removes duplicates.

Another issue is forgetting to provide an equality comparer for custom objects. The code then compiles and runs, but the result is logically wrong.

Developers also often use First() in an aggregate-based approach without guarding against an empty outer collection.

Summary

  • Use Intersect to find distinct values common to two sequences.
  • Chain it or combine it with Aggregate for multiple lists.
  • 'Intersect uses set semantics, so duplicates do not survive.'
  • Provide an IEqualityComparer<T> when intersecting domain objects.
  • Materialize the result if you need to enumerate it more than once.

Course illustration
Course illustration

All Rights Reserved.