Merge Two Arrays in C#: The Ultimate Guide

Merging arrays is one of the most common operations in C#-but how you merge them changes depending on what you’re building. Beginners often think there is only one way to combine two arrays, but in reality, C# gives you multiple merging techniques, each with different performance characteristics, use-cases, and internal behaviours.

This guide explains:

Every major way to merge arrays
How they work internally (copying, memory layout, resizing)
Beginner, intermediate, and advanced examples
LINQ merging, distinct merges, sorted merges, interleaving, flattening
When to use arrays vs List<T> vs Span<T>
…and much more.

Let’s begin.


1. Understanding Arrays in C# Before You Merge Them

Before merging, you should understand how arrays behave in C#:

🔹 Arrays are fixed-size

Once created, you cannot directly resize an array. To “resize,” .NET creates a new array and copies items across.

🔹 Arrays store elements in contiguous memory

This means accessing an element is extremely fast (O(1)), but inserting or merging requires copying (O(n)).

🔹 Copies always allocate new memory

Every merge technique eventually boils down to:

  1. Create a new array of size a.Length + b.Length
  2. Copy a into the new array
  3. Copy b into the new array

Some methods automate this for you (like LINQ), but this is always what’s happening under the hood.


2. The Most Common Method: Using Concat() (LINQ)

⭐ Best for: readability, simplicity, beginner friendliness

❌ Not best for: performance-critical or high-allocation code

int[] a = { 1, 2, 3 };
int[] b = { 4, 5, 6 };

int[] merged = a.Concat(b).ToArray();

What’s happening behind the scenes

  • Concat() creates a lazy sequence (it doesn’t merge yet)
  • .ToArray() forces the merge by:
    • calculating the total length
    • allocating a new array
    • copying both arrays sequentially

Pros

✔ Very clean
✔ No manual loop needed
✔ Easy to chain with .Distinct(), .OrderBy(), etc.

Cons

✘ Creates an iterator + a new array
✘ Not the fastest option


3. Fastest Manual Method: Using Array.Copy()

⭐ Best for: performance, control, large arrays

int[] a = { 1, 2, 3 };
int[] b = { 4, 5, 6 };

int[] merged = new int[a.Length + b.Length];

Array.Copy(a, merged, a.Length);
Array.Copy(b, 0, merged, a.Length, b.Length);

Why this is faster

  • Array.Copy() uses highly optimized internal memory copying
  • No iterator overhead
  • Only a single array allocation

Pros

✔ Fastest merging approach
✔ Precise control
✔ Good for performance-critical code

Cons

✘ More code to write
✘ Not as readable for beginners


4. Merge Using a List<T> (Most Flexible)

⭐ Best for: dynamic merging, unknown number of arrays, convenience

int[] a = { 1, 2, 3 };
int[] b = { 4, 5, 6 };

List<int> mergedList = new List<int>(a.Length + b.Length);
mergedList.AddRange(a);
mergedList.AddRange(b);

int[] merged = mergedList.ToArray();

Why use lists?

  • Lists auto-resize
  • You can add filters, conditions, remove items
  • Best when merging >2 arrays or merging in loops

Pros

✔ Flexible
✔ Easy to extend
✔ Best for dynamic merging

Cons

✘ Slightly more overhead
✘ Still ends in .ToArray() copy


5. Merge With LINQ + Conditions (Filter While Merging)

⭐ Best for: merging only certain elements

int[] a = { 1, 2, 3, 10 };
int[] b = { 4, 5, 6, 12 };

int[] mergedEven = a
    .Concat(b)
    .Where(x => x % 2 == 0)
    .ToArray();

This merges AND filters in one expression.


6. Merge and Remove Duplicates (Distinct())

int[] mergedDistinct = a.Concat(b).Distinct().ToArray();

Under the hood:

  • Builds a hash set
  • Removes duplicates
  • Converts back to array

7. Merge and Sort

int[] mergedSorted = a.Concat(b).OrderBy(x => x).ToArray();

8. Advanced: Interleave Two Arrays

(Useful for zipping data: e.g., alternating items)

Example output

a = {1,3,5}
b = {2,4,6}
{1,2,3,4,5,6}

Code:

int[] Interleave(int[] a, int[] b)
{
    int length = a.Length + b.Length;
    int[] result = new int[length];

    int ai = 0, bi = 0, ri = 0;

    while (ai < a.Length || bi < b.Length)
    {
        if (ai < a.Length) result[ri++] = a[ai++];
        if (bi < b.Length) result[ri++] = b[bi++];
    }
    return result;
}

9. Advanced: Merge Multiple Arrays (N Arrays)

int[][] inputs = {
    new[] {1, 2},
    new[] {3, 4},
    new[] {5, 6}
};

int[] merged = inputs.SelectMany(x => x).ToArray();

SelectMany = flatten array-of-arrays


10. Mega-Fast: Use Span<T> (Advanced .NET technique)

⭐ For: high-performance merging with minimal overhead

(Usually in game engines, financial systems, HPC)

int[] merged = new int[a.Length + b.Length];
Span<int> span = merged;

a.AsSpan().CopyTo(span);
b.AsSpan().CopyTo(span[a.Length..]);

Why it’s fast

  • Uses stack-friendly views over memory
  • Avoids bounds checks
  • No enumerators

This is the closest to “manual memory-level merging” in managed code.


11. When NOT to Use Arrays (Important!)

Choose List<T> or IEnumerable<T> if:

  • You don’t know final size in advance
  • You need to frequently add/remove
  • You’re combining dozens/hundreds of arrays
  • You’re working with streams of data

Arrays are best ONLY when:

  • Size is fixed
  • Highest speed is required
  • Memory layout matters (interop, unsafe, HPC)

12. Which Method Should I Use?

Fastest

➡️ Array.Copy()

Cleanest code

➡️ Concat().ToArray()

Most flexible

➡️ List<T>.AddRange()

For filtering while merging

➡️ Concat().Where()

For deduplication

➡️ .Distinct()

For advanced performance

➡️ Span<T>


13. Complete Practical Example (All Methods Together)

int[] a = { 1, 2, 3 };
int[] b = { 4, 5, 6 };

// 1. Simple merge
var m1 = a.Concat(b).ToArray();

// 2. Fast merge
var m2 = new int[a.Length + b.Length];
Array.Copy(a, m2, a.Length);
Array.Copy(b, 0, m2, a.Length, b.Length);

// 3. List merge
var list = new List<int>(a.Length + b.Length);
list.AddRange(a);
list.AddRange(b);
var m3 = list.ToArray();

// 4. Distinct + sorted
var m4 = a.Concat(b).Distinct().OrderBy(x => x).ToArray();

// 5. Interleave
var m5 = Interleave(a, b);

// 6. Multi-array flatten
int[][] multi = { a, b, new[] { 7, 8 } };
var m6 = multi.SelectMany(x => x).ToArray();