LINQ in Practice · Lesson 15

Chunking with a final partial batch

Partition work while preserving every remaining element.

How it works

Chunk partitions a sequence into arrays whose lengths are at most the requested size. It is useful for pages of local processing, bounded validation groups, or a protocol that accepts a limited number of records per request. The sample chooses a size of two and retains a final one-element batch.

The first output shows the actual contents: one and two, then three and four, then five. The second output makes the boundary visible through lengths two, two, one. Code consuming a chunk should iterate its actual contents instead of assuming every batch is full. An incomplete final batch is an ordinary case, not necessarily an error.

Materializing the chunks with ToArray captures all batches for repeated inspection in this small lesson. For a large source, process each chunk as it arrives instead of keeping every batch unless a snapshot is required. The arrays created for chunks are additional storage, so batch size affects allocation and downstream workload.

A common mistake is confusing batch size with concurrency. Chunk(2) groups records in twos; it does not itself start two tasks, limit active operations, or wait for asynchronous processing. Those execution policies belong in the consumer. Keeping grouping and scheduling separate makes the behavior easier to test.

Practice with an empty sequence, a single element, and a sequence whose length is exactly divisible by two. Predict the number of chunks and each length for every case. Then change the size to three and verify that flattening the chunks reproduces the original sequence in its original order.

Finally, write a consumer that calculates a sum per chunk and a grand total. Compare the sum of batch totals with a direct sum of the source. That invariant catches skipped remainders and duplicated batches. Validate a configurable size before using it, because zero or a negative size cannot describe a meaningful chunk boundary.

A working example

using System;
using System.Linq;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.CompilerServices;

int[] values = { 1, 2, 3, 4, 5 };
var chunks = values.Chunk(2).ToArray();
Console.WriteLine(string.Join("|", chunks.Select(chunk => string.Join(",", chunk))));
Console.WriteLine(string.Join(",", chunks.Select(chunk => chunk.Length)));

Expected output

1,2|3,4|5
2,2,1
Try this
The final chunk can contain fewer than the requested number of elements.