Click here to Skip to main content
15,903,362 members
Articles / Programming Languages / C#
Tip/Trick

Who knows Enumerable.Range(...)?

Rate me:
Please Sign up or sign in to vote.
4.97/5 (13 votes)
19 Apr 2012CPOL 63.7K   18  
Make loops behave deterministic-by-construction.
This is an old version of the currently published tip/trick.

Introduction

I quite often see constructs like

C#
for(int n = 0; n < len; ++n)
{
   //... some more or less complex conditional control flow...
   n = 5; // causes the loop to never terminate if len is greater than 5
   //... some more code ...
}
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:
C#
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.
C#
foreach (int n in Enumerable.Range(0, len))
{
    n = 5; // Compiler error!
}
Note: Enumerable.Range(...) is not from, to, but from, count:
C#
//
// Summary:
//     Generates a sequence of integral numbers within a specified range.
//
// Parameters:
//   start:
//     The value of the first integer in the sequence.
//
//   count:
//     The number of sequential integers to generate.
//
// Returns:
//     An IEnumerable<Int32> in C# or IEnumerable(Of Int32) in Visual Basic that
//     contains a range of sequential integral numbers.
//
// Exceptions:
//   System.ArgumentOutOfRangeException:
//     count is less than 0.-or-start + count -1 is larger than System.Int32.MaxValue.
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.
C#
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...
C#
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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Founder eXternSoft GmbH
Switzerland Switzerland
I feel comfortable on a variety of systems (UNIX, Windows, cross-compiled embedded systems, etc.) in a variety of languages, environments, and tools.
I have a particular affinity to computer language analysis, testing, as well as quality management.

More information about what I do for a living can be found at my LinkedIn Profile and on my company's web page (German only).

Comments and Discussions

Discussions on this specific version of this article. Add your comments on how to improve this article here. These comments will not be visible on the final published version of this article.