C#
programming
integers
sequence
tutorial

How to create a sequence of integers in C?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Creating integer sequences in C# is a common task in iteration, test data generation, and range-based processing. You can build sequences with loops, Enumerable.Range, iterators, or custom step logic. The best choice depends on readability, performance expectations, and whether you need lazy evaluation.

Enumerable.Range for Standard Sequences

For contiguous ascending ranges, Enumerable.Range is usually the cleanest option.

csharp
1using System;
2using System.Linq;
3
4public static class Program
5{
6    public static void Main()
7    {
8        var seq = Enumerable.Range(start: 1, count: 10);
9        Console.WriteLine(string.Join(", ", seq));
10    }
11}

This creates values from 1 to 10 lazily. It is concise and idiomatic.

Traditional Loop for Full Control

A for loop is best when you need custom bounds, side effects, or mutable accumulation.

csharp
1using System;
2using System.Collections.Generic;
3
4public static class Program
5{
6    public static void Main()
7    {
8        var values = new List<int>();
9        for (int i = 5; i <= 25; i += 5)
10        {
11            values.Add(i);
12        }
13
14        Console.WriteLine(string.Join(" | ", values));
15    }
16}

This style is explicit and easy to debug.

Generate Sequences With Custom Step

Enumerable.Range does not support arbitrary step sizes directly. Combine it with projection:

csharp
1using System;
2using System.Linq;
3
4public static class Program
5{
6    public static void Main()
7    {
8        int start = 10;
9        int step = 3;
10        int count = 8;
11
12        var seq = Enumerable.Range(0, count)
13                            .Select(i => start + i * step);
14
15        Console.WriteLine(string.Join(", ", seq));
16    }
17}

This works for arithmetic progressions and remains lazy until enumerated.

Descending Sequences

For descending order, use reverse projection or loop.

csharp
1using System;
2using System.Linq;
3
4public static class Program
5{
6    public static void Main()
7    {
8        var descending = Enumerable.Range(0, 6)
9                                   .Select(i => 20 - i * 2);
10
11        Console.WriteLine(string.Join(", ", descending));
12    }
13}

You can also generate ascending first and call Reverse, but direct expression is often clearer.

Iterator Method for Reusable Ranges

When sequence rules are reused in multiple places, create an iterator method with yield return.

csharp
1using System;
2using System.Collections.Generic;
3
4public static class SequenceBuilder
5{
6    public static IEnumerable<int> RangeStep(int start, int endInclusive, int step)
7    {
8        if (step == 0)
9            throw new ArgumentException("step must not be zero", nameof(step));
10
11        if (step > 0)
12        {
13            for (int v = start; v <= endInclusive; v += step)
14                yield return v;
15        }
16        else
17        {
18            for (int v = start; v >= endInclusive; v += step)
19                yield return v;
20        }
21    }
22}
23
24public static class Program
25{
26    public static void Main()
27    {
28        var seq = SequenceBuilder.RangeStep(12, -3, -3);
29        Console.WriteLine(string.Join(", ", seq));
30    }
31}

This gives flexibility for both ascending and descending generation.

Materialized Versus Lazy Sequences

LINQ sequences are lazy by default. If you need repeated indexed access, materialize once.

csharp
var arr = Enumerable.Range(1, 1000).ToArray();

Lazy evaluation is memory-efficient for single-pass processing. Materialization is better when iterating many times.

Performance Notes

Enumerable.Range is optimized and generally fast for simple integer ranges. For very hot loops in performance-critical code, direct loops may still be preferable due to reduced iterator overhead and allocation behavior in surrounding operations.

Benchmark before optimizing. In many business applications, readability gains from LINQ outweigh micro-optimizations.

Common Pitfalls

  • Confusing count with end value in Enumerable.Range.
  • Using step logic with potential zero step and no validation.
  • Materializing large ranges unnecessarily with ToList or ToArray.
  • Re-enumerating lazy sequences repeatedly when caching is needed.
  • Using descending logic incorrectly with positive step values.

Summary

  • Use Enumerable.Range for simple ascending contiguous sequences.
  • Use loop or projection for custom step sizes and descending patterns.
  • Iterator methods with yield return provide reusable sequence builders.
  • Decide between lazy and materialized sequences based on access pattern.
  • Validate range and step assumptions to prevent subtle logic errors.

Course illustration
Course illustration