C#
IEnumerable
LINQ
programming
collections

How to concatenate two IEnumerableT into a new IEnumerableT?

Interview Questions practice on Codemia

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

Browse interview questions

Introduction

In C#, the standard way to concatenate two IEnumerable<T> sequences is Concat. It creates a new deferred sequence that enumerates the first source and then the second, which is usually exactly what you want unless you need an eager materialized snapshot instead.

Use Concat for the Normal Case

LINQ already provides the standard solution.

csharp
1using System;
2using System.Collections.Generic;
3using System.Linq;
4
5class Program
6{
7    static void Main()
8    {
9        IEnumerable<int> first = new[] { 1, 2, 3 };
10        IEnumerable<int> second = new[] { 4, 5, 6 };
11
12        IEnumerable<int> combined = first.Concat(second);
13
14        foreach (var value in combined)
15        {
16            Console.WriteLine(value);
17        }
18    }
19}

This produces a new IEnumerable<int> that yields 1, 2, 3, 4, 5, 6.

The important detail is that Concat is deferred. It does not copy elements immediately. It simply builds a sequence pipeline that will enumerate both sources later.

Know When You Actually Need a Materialized Collection

If you need a concrete list or array, materialize after concatenation.

csharp
1using System.Collections.Generic;
2using System.Linq;
3
4IEnumerable<string> a = new[] { "A", "B" };
5IEnumerable<string> b = new[] { "C", "D" };
6
7List<string> list = a.Concat(b).ToList();

This is useful when:

  • you need random access
  • you need a stable snapshot
  • the source sequences may change later

Without ToList or ToArray, the combined sequence will keep pulling from the original enumerables whenever it is iterated.

Handle Null Sources Explicitly

Concat throws if either sequence is null, so guard optional inputs when needed.

csharp
1using System.Collections.Generic;
2using System.Linq;
3
4IEnumerable<int> first = null;
5IEnumerable<int> second = new[] { 10, 20 };
6
7IEnumerable<int> safeCombined =
8    (first ?? Enumerable.Empty<int>())
9    .Concat(second ?? Enumerable.Empty<int>());

This pattern is cleaner than scattering null checks through the calling code.

Understand Deferred Execution

Because Concat is deferred, iteration happens later, not when the expression is built.

csharp
1using System;
2using System.Collections.Generic;
3using System.Linq;
4
5var first = new List<int> { 1, 2 };
6var second = new List<int> { 3, 4 };
7
8var combined = first.Concat(second);
9first.Add(99);
10
11Console.WriteLine(string.Join(", ", combined));

This prints 1, 2, 99, 3, 4 because the lists were enumerated after the modification. If that is not what you want, materialize immediately with ToList().

Custom Iterator Is Rarely Necessary

You can write your own iterator, but it is usually unnecessary unless you need custom behavior beyond simple concatenation.

csharp
1using System.Collections.Generic;
2
3public static IEnumerable<T> Combine<T>(IEnumerable<T> first, IEnumerable<T> second)
4{
5    foreach (var item in first)
6        yield return item;
7
8    foreach (var item in second)
9        yield return item;
10}

This works, but it is effectively what Concat already provides. Prefer the built-in LINQ method unless you need special rules such as filtering, deduplication, or instrumentation.

Common Pitfalls

  • Forgetting that Concat is deferred can make later source mutations appear unexpectedly in the combined sequence.
  • Calling Concat on a null sequence throws unless you guard with Enumerable.Empty<T>().
  • Assuming Concat deduplicates elements is wrong; it preserves order and includes duplicates.
  • Materializing too early can waste memory when deferred iteration would have been fine.
  • Writing a custom concatenation iterator for the simple case usually adds code without adding value.

Summary

  • Use Enumerable.Concat for the standard way to combine two IEnumerable<T> sequences.
  • Materialize with ToList() or ToArray() when you need a concrete snapshot.
  • Guard optional inputs with Enumerable.Empty<T>() to avoid null-related errors.
  • Remember that Concat preserves order and does not remove duplicates.
  • Prefer the built-in LINQ method unless you need custom concatenation behavior.

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.