How to Use the LINQ Zip Operator in C
The Zip operator in C# LINQ merges two sequences into a
single result sequence by pairing elements that share the same index.
This article explains how the Zip method operates, how it
handles sequences of unequal lengths, and how to implement it using
custom result selectors or C# value tuples.
What is the Zip Operator?
The Zip extension method is part of the
System.Linq namespace. It walks through two enumerable
sequences in parallel, taking one element from the first sequence and
the corresponding element from the second sequence, then combining them
into a new element.
Its name comes from the concept of a physical zipper, where teeth from both sides interlock sequentially one by one.
Basic Syntax and Usage
The Zip method has two primary overloads: one that takes
a result selector function, and another (introduced in .NET Core 3.0)
that directly combines elements into value tuples.
1. Using a Result Selector Function
You provide a lambda expression that defines how the paired elements should be transformed.
using System;
using System.Linq;
class Program
{
static void Main()
{
int[] numbers = { 1, 2, 3 };
string[] words = { "One", "Two", "Three" };
var combined = numbers.Zip(words, (num, word) => $"{num}: {word}");
foreach (var item in combined)
{
Console.WriteLine(item);
}
}
}Output:
1: One
2: Two
3: Three
2. Using Tuple Projections (.NET Core 3.0+)
If you do not provide a selector function, Zip
automatically produces a sequence of (TFirst, TSecond)
value tuples.
int[] ids = { 101, 102, 103 };
string[] names = { "Alice", "Bob", "Charlie" };
var pairs = ids.Zip(names);
foreach (var (id, name) in pairs)
{
Console.WriteLine($"ID: {id}, Name: {name}");
}Handling Sequences of Unequal Length
When the two input sequences do not have the same number of elements,
Zip stops processing as soon as it reaches the end of the
shorter sequence. Any remaining elements in the longer sequence are
ignored.
int[] shortList = { 1, 2 };
string[] longList = { "A", "B", "C", "D" };
var result = shortList.Zip(longList, (n, s) => $"{n}-{s}");
// Result contains only two items: "1-A", "2-B"Zipping Three Sequences (.NET 6+)
Starting with .NET 6, LINQ supports combining three sequences directly using an overload that takes two additional sequences:
int[] ids = { 1, 2 };
string[] names = { "Widget", "Gadget" };
decimal[] prices = { 9.99m, 14.50m };
var products = ids.Zip(names, prices);
foreach (var (id, name, price) in products)
{
Console.WriteLine($"{id}: {name} costs ${price}");
}Key Characteristics of Zip
- Deferred Execution: Like most LINQ operators,
Zipevaluates lazily. It does not iterate over either sequence until the result is enumerated (e.g., viaforeach,ToList(), orToArray()). - Streaming Behavior: Elements are read on demand. It does not need to buffer the entire collection in memory to yield paired results.
- Null Reference Handling: Calling
Zipon anullcollection or passing anullsecond sequence throws anArgumentNullException.