Does C have a nice way of iterating through every integer in a range, minus 1 of them?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
In C#, iterating across a numeric range while skipping one specific value is common and does not require anything exotic. The right approach depends on whether you want maximum clarity, minimum allocation, or a more declarative LINQ style.
The Simple and Fast Approach
For most cases, a plain for loop with continue is the best answer. It is explicit, efficient, and easy to debug.
This prints every integer from 1 through 10 except 5. If you only need iteration, this is usually the cleanest implementation.
A LINQ Version for Declarative Code
If the surrounding code already uses LINQ and you want a sequence you can pass around, Enumerable.Range combined with Where is a good fit.
The tradeoff is that this is slightly less direct than a loop, and you need to remember that Enumerable.Range takes a start and a count, not a start and an end.
Excluding More Than One Value
If the requirement grows from "skip one number" to "skip a set of numbers," the loop still works, but a HashSet<int> makes the intent cleaner and keeps lookups fast.
That scales better than chaining many if checks once the skip logic becomes more dynamic.
When You Actually Need a Reusable Iterator
If the pattern appears in several places, wrap it in an iterator method. This preserves readability without paying the cost of building a list eagerly.
This becomes useful when the iteration pattern is part of your domain logic, not just a one-off loop.
Choosing Between the Options
Use a for loop when:
- performance matters
- the logic is local
- you want the fewest moving parts
Use LINQ when:
- you need to compose a sequence with other filters
- you are already working in a query-heavy code path
- readability benefits from a declarative style
Use a custom iterator when:
- the pattern is reused
- the exclusion rule belongs in a named abstraction
There is no deeper language trick here. The nice way is the one that matches the job.
Edge Cases Worth Checking
You should still think through the boundaries:
- what happens if
startis greater thanend - whether the range is inclusive or exclusive
- whether the excluded number falls outside the range
For example, if excluded is 99 and the range is 1 to 10, nothing special should happen. That is usually fine, but it is worth making deliberate.
Common Pitfalls
The most common mistake with LINQ is forgetting that Enumerable.Range(start, count) expects a count, not the final value. Using Enumerable.Range(1, 10) is correct for 1 through 10, but Enumerable.Range(5, 10) gives 5 through 14, not 5 through 10.
Another mistake is reaching for a clever abstraction too early. A plain loop is often better than a helper method or query chain if the logic appears once.
Developers also sometimes build a full list just to iterate it once. If you only need streaming iteration, prefer yield return or a direct loop.
Finally, be explicit about whether the upper bound is included. Many off-by-one bugs come from mixing inclusive and exclusive range rules.
Summary
- In C#, the simplest solution is usually a
forloop withcontinue. - '
Enumerable.Range(...).Where(...)is a good declarative alternative when you need a composable sequence.' - A custom iterator with
yield returnis useful when the pattern is reused. - Be careful with
Enumerable.Range, because its second argument is a count. - Decide on inclusive versus exclusive bounds up front to avoid off-by-one errors.

