Introduction
I quite often see constructs like
for(int n = 0; n < len; ++n)
{
n = 5;
}
This is a legal language construct, but it introduces the danger of non-determinism.
This tip aims to show some deterministic alternative to that plain for
loop.
Using the code
If you need to loop over some range of integer, consider using the
Enumerable.Range[
^] based
foreach
loop instead:
using System.Linq;
...
foreach (int n in Enumerable.Range(0, len))
{
...
}
This guarantees that it iterates over all elements in strict sequence. Another benefit is, that you can not assign any other value to the loop variable
n
. E.g.
foreach (int n in Enumerable.Range(0, len))
{
n = 5;
}
Note: Enumerable.Range(...)
is
not from,
to, but
from,
count:
public static IEnumerable<int> Range(int start, int count);
Alternatives
One could also build his own iterator functions (see also
C# Iterator Pattern demystified[
^]).
E.g.
public static IEnumerable<int> CountUp(int n, int count)
{
while (count-- > 0) yield return n++;
}
public static IEnumerable<int> CountDown(int n, int count)
{
while (count-- > 0) yield return n--;
}
When used like this...
foreach (int n in CountUp(0, 5)) Console.WriteLine(n);
foreach (int n in CountDown(100, 5)) Console.WriteLine(n);
...results in:
0
1
2
3
4
100
99
98
97
96
You can define any complexity of traversing sequence in that function and let the foreach-loop terminate deterministically, based on that sequence.
Advise
Try to avoid plain
for (...)
loops and replace by some deterministic loop alternative like
foreach( ... Range(...))
foreach( ... CountUp(...))
- etc.
Other alternatives are Linq iterations like
Enumerable.Aggregate[
^] etc. But these are a bit more advanced.
History
2012-04-18 first version
2012-04-19 added hand-crafted CountUp/CountDown functions.