Click here to Skip to main content
15,881,709 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)
14 Apr 2013CPOL 63.1K   18   20
Make loops behave deterministic-by-construction

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 alternatives 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 cannot 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
  • 2013-04-14 Fixed some broken HTML markup in C# code generics

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

 
GeneralMy vote of 5 Pin
Adam Mendoza22-Apr-13 23:06
Adam Mendoza22-Apr-13 23:06 
GeneralRe: My vote of 5 Pin
Andreas Gieriet23-Apr-13 12:59
professionalAndreas Gieriet23-Apr-13 12:59 
Generalovercoming "from, count" Pin
Matt T Heffron15-Apr-13 7:38
professionalMatt T Heffron15-Apr-13 7:38 
GeneralRe: overcoming "from, count" Pin
Andreas Gieriet15-Apr-13 10:33
professionalAndreas Gieriet15-Apr-13 10:33 
GeneralRe: overcoming "from, count" Pin
Matt T Heffron15-Apr-13 10:43
professionalMatt T Heffron15-Apr-13 10:43 
GeneralRe: overcoming "from, count" Pin
Andreas Gieriet15-Apr-13 12:02
professionalAndreas Gieriet15-Apr-13 12:02 
GeneralRe: overcoming "from, count" Pin
Matt T Heffron15-Apr-13 12:09
professionalMatt T Heffron15-Apr-13 12:09 
QuestionAnother readability optimization Pin
paul.vencill15-Apr-13 1:09
paul.vencill15-Apr-13 1:09 
Good article, Andreas. I have liked Enumerable.Range() since shortly after LINQ came out. I've found generally that the sizes of Enumerables I build with it are small enough that the performance hit for not using for... is negligible.

One thing that I like to do to go one step further with it is to continue using LINQ in the statement rather than just using the Range() as a parameter of the foreach. For example, if I'm running a unit test and I need five users (for example), I might do something like this:

C#
var users = Enumerable.Range(0,5).Select(n=> new User());


Lots of constructs can be built that way, whether you need the index number or not.
AnswerRe: Another readability optimization Pin
Andreas Gieriet15-Apr-13 5:50
professionalAndreas Gieriet15-Apr-13 5:50 
GeneralThoughts Pin
PIEBALDconsult14-Apr-13 15:30
mvePIEBALDconsult14-Apr-13 15:30 
GeneralMy vote of 5 Pin
Kenneth Haugland3-Sep-12 13:53
mvaKenneth Haugland3-Sep-12 13:53 
GeneralRe: My vote of 5 Pin
Andreas Gieriet3-Sep-12 20:21
professionalAndreas Gieriet3-Sep-12 20:21 
GeneralPros and Cons and ... Pin
Jani Giannoudis18-Apr-12 12:26
Jani Giannoudis18-Apr-12 12:26 
GeneralRe: Pros and Cons and ... Pin
Andreas Gieriet18-Apr-12 21:22
professionalAndreas Gieriet18-Apr-12 21:22 
QuestionYour problem is not the for... Pin
Paulo Zemek18-Apr-12 9:48
mvaPaulo Zemek18-Apr-12 9:48 
AnswerRe: Your problem is not the for... Pin
Andreas Gieriet18-Apr-12 10:56
professionalAndreas Gieriet18-Apr-12 10:56 
GeneralRe: Your problem is not the for... Pin
Paulo Zemek18-Apr-12 14:10
mvaPaulo Zemek18-Apr-12 14:10 
GeneralRe: Your problem is not the for... Pin
Andreas Gieriet18-Apr-12 18:05
professionalAndreas Gieriet18-Apr-12 18:05 
AnswerRe: Your problem is not the for... Pin
TimothyP22-Apr-13 8:26
TimothyP22-Apr-13 8:26 
GeneralRe: Your problem is not the for... Pin
Andreas Gieriet22-Apr-13 8:45
professionalAndreas Gieriet22-Apr-13 8:45 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.