C#
sublist
programming
coding
tutorial

How to Get a Sublist in C

Interview Questions practice on Codemia

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

Browse interview questions

Introduction

Getting a sublist in C# is a common operation for pagination, batching, and windowed processing. The best API depends on whether you need a new list copy, a lazy sequence, or a span-like view over contiguous memory. Choosing the right option improves both readability and performance.

GetRange for Concrete List<T> Copies

If you already have a List<T> and need another list, GetRange is direct and clear.

csharp
1using System;
2using System.Collections.Generic;
3
4var numbers = new List<int> { 10, 20, 30, 40, 50, 60 };
5List<int> sub = numbers.GetRange(2, 3); // 30, 40, 50
6
7Console.WriteLine(string.Join(", ", sub));

GetRange(startIndex, count) creates a copy, so modifying sub does not alter the original list.

Skip and Take for Query Pipelines

For enumerable pipelines, LINQ is often more composable.

csharp
1using System;
2using System.Linq;
3
4int[] values = { 1, 2, 3, 4, 5, 6, 7, 8 };
5var page = values.Skip(2).Take(4).ToList();
6
7Console.WriteLine(string.Join(" | ", page));

This style is useful when sublist selection is part of filtering and projection chains.

Range Operator for Arrays and Spans

Modern C# supports range syntax for arrays and spans.

csharp
1using System;
2
3int[] arr = { 5, 10, 15, 20, 25, 30 };
4int[] slice = arr[1..4]; // 10, 15, 20
5
6Console.WriteLine(string.Join(", ", slice));

For performance-sensitive paths, use spans to avoid unnecessary allocations.

csharp
1using System;
2
3int[] arr = { 100, 200, 300, 400, 500 };
4Span<int> view = arr.AsSpan(1, 3);
5
6for (int i = 0; i < view.Length; i++)
7{
8    Console.WriteLine(view[i]);
9}

Span-based slices reference the original memory, so updates affect source data.

Safe Sublist Helper

In application code, indices can be user-provided and invalid. A safe helper avoids repeated boundary checks.

csharp
1using System;
2using System.Collections.Generic;
3
4public static class ListUtils
5{
6    public static List<T> SublistSafe<T>(IReadOnlyList<T> source, int start, int count)
7    {
8        if (start < 0 || count < 0 || start > source.Count)
9            throw new ArgumentOutOfRangeException();
10
11        int end = Math.Min(source.Count, start + count);
12        var result = new List<T>(end - start);
13
14        for (int i = start; i < end; i++)
15            result.Add(source[i]);
16
17        return result;
18    }
19}

This pattern is explicit and robust for API-layer inputs.

Pagination and Batch Processing Example

Sublist logic appears frequently in pagination APIs and worker batching. A clean pattern calculates start offset from page number and page size, then slices safely.

csharp
1using System;
2using System.Collections.Generic;
3using System.Linq;
4
5public static class Paging
6{
7    public static List<T> Page<T>(IReadOnlyList<T> source, int pageNumber, int pageSize)
8    {
9        if (pageNumber < 1) throw new ArgumentOutOfRangeException(nameof(pageNumber));
10        if (pageSize < 1) throw new ArgumentOutOfRangeException(nameof(pageSize));
11
12        int start = (pageNumber - 1) * pageSize;
13        if (start >= source.Count) return new List<T>();
14
15        int count = Math.Min(pageSize, source.Count - start);
16        var result = new List<T>(count);
17        for (int i = start; i < start + count; i++)
18        {
19            result.Add(source[i]);
20        }
21        return result;
22    }
23}
24
25var items = Enumerable.Range(1, 23).ToList();
26var page3 = Paging.Page(items, pageNumber: 3, pageSize: 10);
27Console.WriteLine(string.Join(",", page3));

This method keeps behavior deterministic at boundaries, including partial final pages and empty out-of-range pages.

For high-throughput systems, benchmark whether list copies are necessary. If downstream code only reads data once, lazy enumerables or spans can reduce allocation pressure.

Common Pitfalls

A common pitfall is confusing count with endIndex when using GetRange.

Another issue is forgetting that LINQ Skip and Take are lazy until materialized. If source changes before enumeration, results may differ from expectations.

Developers also create many temporary sublists inside tight loops, increasing allocations.

Finally, always validate indices. Out-of-range errors are easy to trigger in pagination and batch APIs.

Summary

  • Use GetRange for straightforward list copies.
  • Use LINQ for composable query-style sublist selection.
  • Use range syntax and spans for modern, efficient slicing patterns.
  • Add safe helpers when index inputs are external.
  • Match approach to performance and mutability needs.

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.