HomeSearch

C# for Loop Examples

Iterate over numbers with for. Increment or decrement an index int from a start to an end value.

For.

You feel a gust of wind. A branch on a nearby tree rustles. In nature these phenomena are all around us. Our world is full of motion.

In a for-loop,

we iterate through a series of numbers. We progress from one point to another. Like the wind we travel in a path. We loop over a range.

A for-loop.

Here, the name of the variable "i" is a convention. It is easier for other programmers to understand than unusual variable names.

Start: The loop starts at the value 0. In C# most collections are zero-based, so the first element is at 0.

End: The loop continues running through the body until "i" equals 10 (or some other value if it is set elsewhere).

Increment: Please note the third clause in the for-loop, the i++ part. This is the iteration statement—it occurs after each pass.

C# program that uses increment loop using System; class Program { static void Main() { for (int i = 0; i < 10; i++) { Console.WriteLine(i); } } } Output 0 1 2 3 4 5 6 7 8 9

Decrement loop.

This is a simple example. A for-loop can decrement in the step condition. Here we start at 10, and continue until 0 is reached.
C# program that uses decrement loop using System; class Program { static void Main() { for (int i = 10 - 1; i >= 0; i--) { Console.WriteLine(i); } } } Output 9 8 7 6 5 4 3 2 1 0

Iteration step.

The third clause in the for-loop is the step. This can change the variable (or any variable) by any amount—a constant is not even needed.

Two: Here we add two after each pass through the loop. So we skip odd number indexes.

C# program that uses step increment loop using System; class Program { static void Main() { for (int i = 0; i < 10; i += 2) { Console.WriteLine(i); } } } Output 0 2 4 6 8

Decrement, step.

This program revisits loop decrementing. It decreases the iteration variable by two each time. The example is simple and straightforward.
C# program that uses step decrement loop using System; class Program { static void Main() { for (int i = 10 - 1; i >= 0; i -= 2) { Console.WriteLine(i); } } } Output 9 7 5 3 1

Expression, maximum bound.

Complex expressions, even method calls, can be used in the conditions of a for-loop. This can help simplify code.

However: Be careful not to call an expensive function too much. Unneeded operations can end up executing.

C# program that uses expression in maximum bounds using System; class Program { static void Main() { for (int i = 0; i < (20 / 2); i += 2) { Console.WriteLine(i); } } } Output 0 2 4 6 8

First part.

When a for-loop is encountered, the first of the three statements is executed. The for-loop shown first has its "int i = 0" statement executed.

Tip: We can start a for-loop with any value for the iteration variable. The value does not need to be a constant.

Second part: Evaluated before the first iteration, and after each execution. If this is true, the loop proceeds. If false, it stops.

True, False

Third part: Specifies how the iteration variable (i) changes after each successful iteration.

Empty statements.

We can omit statements in the for-loop. With empty statements, we just see some semicolons. No action is taken on each iteration—this is like a while true loop.
C# program that shows empty for-statements using System; class Program { static void Main() { int i = 0; // Use for-loop with empty statements. for (; ; ) { if (i > 4) { break; } Console.WriteLine("EMPTY FOR-LOOP: " + i); i++; } } } Output EMPTY FOR-LOOP: 0 EMPTY FOR-LOOP: 1 EMPTY FOR-LOOP: 2 EMPTY FOR-LOOP: 3 EMPTY FOR-LOOP: 4

For, 2 variables.

We can use 2 variables in a for-loop statement. Here we initialize "i" and "x" to zero, and increment "i" and decrement "x."

Tip: We use commas to separate statements. For the termination condition, we can just use 1 expression with the && operator.

C# program that loops over 2 variables class Program { static void Main() { // Loop over 2 variables at once. for (int i = 0, x = 0; i < 10 && x >= -2; i++, x--) { System.Console.WriteLine("FOR: i={0}, x={1}", i, x); } } } Output FOR: i=0, x=0 FOR: i=1, x=-1 FOR: i=2, x=-2

Chars.

A for-loop often uses an int index. But other index types are possible. Here I use a char variable and loop over all the lowercase letters.

Tip: Often a for-loop over chars is useful for initializing a lookup table. Each char is accessed separately.

ROT13
C# program that uses for, char range using System; class Program { static void Main() { // ... Loop over character range. for (char c = 'a'; c <= 'z'; c++) { Console.WriteLine(c); } } } Output a b c d e....

Variable names.

In isolated, small loops, a simple name such as the famous "i" is a good choice. It is standard. It is short. It is easy to type and remember.

But: If the variable is used to access an array, you can change the name to a more descriptive word to indicate its purpose.

Letter i: This identifier has no importance. It is simply a tradition. The book Code Complete by Steve McConnell has great detail here.

A name mistake.

Single-letter loop iteration variables seem convenient. But what happens when we have nested loops, and mistake "i" for "j?" Sometimes more descriptive names are better.

Compilers.

Programs commonly spend most of their time in tight loops such as for-loops. Compilers put considerable effort into speeding up these constructs. This is worthwhile.

Note: Fields of mathematics such as linear algebra can be used to analyze data reuse and data dependence in for-loops.

Note 2: Compilers use techniques such as strength reduction to improve performance of affine expressions based on iteration variables.

Strings.

All kinds of loops work with strings. But the for-loop is often preferable for its syntax and index variable. Testing chars directly is fastest.

For, Foreach: An example shows a string being looped over with for and foreach in the same way. For gives us an index to use.

Loop, String Chars

Performance: Make sure not to use ToString in a loop if you do not need it. Improve performance by not using ToString in a for-loop.

Loop, ToString

Next: We see a simple loop through the characters in the constant string literal "Rome." All 4 are printed to the console.

C# program that uses for-loop over string chars class Program { static void Main() { string value = "Rome"; // Use for-loop from 0 through Length of string (goes to last index). for (int i = 0; i < value.Length; i++) { char current = value[i]; System.Console.WriteLine(current); } } } Output R o m e

Local function, max.

Suppose we need some logic to determine the max bound of a for-loop. Instead of repeating it, we can place it in a local function.

Math.Min: The Math.Min function is sometimes useful in this situation too—it can prevent us from going off the end of an array.

Math.Max
C# program that uses local function for loop max using System; class Program { static void Main() { // Use this local function to safely get a top bound for a for-loop. int Limit(int max, int[] array) { return Math.Min(max, array.Length); } int[] values = { 10, 20, 30, 40 }; // Continue to index 2. for (int i = 0; i < Limit(2, values); i++) { Console.WriteLine("LIMIT 2: " + values[i]); } // Continue to index 10 (or array length). for (int i = 0; i < Limit(10, values); i++) { Console.WriteLine("LIMIT 10: " + values[i]); } } } Output LIMIT 2: 10 LIMIT 2: 20 LIMIT 10: 10 LIMIT 10: 20 LIMIT 10: 30 LIMIT 10: 40

Arrays, 2d arrays.

Loop constructs can be used upon arrays and 2D arrays. With 1D arrays, the code is straightforward. But with 2D arrays, we must divide our indexes to correctly loop.Loop, ArrayLoop, String ArrayLoop, 2D Array

Performance.

The for-loop is often the fastest way to loop over a series of numbers. It does not require allocations. It is easy for the compiler to optimize.

Array: The JIT compiler can detect array accesses in a for-loop. It can determine the iteration variable will never be out-of-bounds.

Then: It can automatically removes array bounds checking. Because of this, the simplest for-loops are sometimes fastest.

For optimization, intro.

How can we make loops go faster? We can try code tuning loops. Consider "jamming" loops, unrolling loops, and changing a loop to decrement and test against 0.

For optimization, jammed.

Suppose we have 2 loops that iterate over the same range. If the latter ones do not depend on changes made in the earlier loops, we can merge or "jam" them.

Here: We want to set 3 values in an array repeatedly. There is no data dependence between the 3 operations.

So: In Method1 we see the "jammed" loops merged into 1 loop, and in Method2 we see the unoptimized code.

Result: The "jammed" loop, where we make a single pass from start to end, is measurably (and consistently) faster.

Warning: If the indexes are not the same in 2 loops, we could add branches (ifs) in the jammed loop, but this might be slower.

C# program that uses jammed loop optimization using System; using System.Diagnostics; class Program { const int _max = 1000000; static void Main() { int[] data = new int[10]; // Version 1: use jammed loop method. var s1 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { Method1(data); } s1.Stop(); // Version 2: use separate loops. var s2 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { Method2(data); } s2.Stop(); Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) / _max).ToString("0.00 ns")); Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) / _max).ToString("0.00 ns")); } static void Method1(int[] array) { // Use "jammed" loop. for (int i = 0; i < array.Length; i++) { array[0] = i; array[1] = i; array[2] = i; } } static void Method2(int[] array) { // Use 3 separate loops. for (int i = 0; i < array.Length; i++) { array[0] = i; } for (int i = 0; i < array.Length; i++) { array[1] = i; } for (int i = 0; i < array.Length; i++) { array[2] = i; } } } Output 9.11 ns Jammed for-loop (1) 13.39 ns Separate for-loops (3)

For optimization, unwinding.

A loop can process just one operation at a time. But sometimes we can place 2 or more operations in an iteration. This is called loop unrolling or unwinding.

Important: We must be sure to only use this when we know that the size of the loop is divisible by the number of operations.

Here: We test 1 array element per iteration, then in the second method, we test 2 array elements per iteration—and increment by 2.

Result: Acting on 2 array elements per iteration is faster. For small arrays, or arrays of uncertain size, this optimization may not work.

C# program that uses loop unwinding optimization using System; using System.Diagnostics; class Program { const int _max = 100000; static void Main() { int[] data = new int[100]; // Version 1: loop over each element. var s1 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { Method1(data); } s1.Stop(); // Version 2: loop over 2 elements at a time (use loop unwinding). var s2 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { Method2(data); } s2.Stop(); Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) / _max).ToString("0.00 ns")); Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) / _max).ToString("0.00 ns")); } static void Method1(int[] array) { // If element is 3, change it to 0. for (int i = 0; i < array.Length; i++) { if (array[i] == 3) { array[i] = 0; } } } static void Method2(int[] array) { // Handle 2 elements in each iteration, and increment by 2. // ... Uses loop unwinding. for (int i = 0; i < array.Length; i += 2) { if (array[i] == 3) { array[i] = 0; } if (array[i + 1] == 3) { array[i + 1] = 0; } } } } Output 112.84 ns Test 1 element per iteration 65.97 ns Test 2 elements, i += 2, loop unwinding

For optimization, decrement.

Many CPUs can compare against 0 faster. We can use this to optimize a for-loop. We start at the max, decrement, and then compare against zero each iteration.

Here: Look at the inner loops of Method1 and Method2. In Method1, we start at the max, decrement by 1, and compare against 0.

And: In Method2, we start at 0, and continue until we reach the max—so we compare against a non-zero number each time.

Result: The test-against-zero optimization makes the loop a tiny bit faster. Even when tested on a newer PC (in late 2018) this is true.

C# program that uses decrement to zero optimization using System; using System.Diagnostics; class Program { const int _max = 1; static void Main() { // Version 1: decrement to zero. var s1 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { Method1(10, 100000000); } s1.Stop(); // Version 2: increment to max. var s2 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { Method2(10, 100000000); } s2.Stop(); Console.WriteLine(s1.Elapsed.TotalMilliseconds.ToString("0.00 ms")); Console.WriteLine(s2.Elapsed.TotalMilliseconds.ToString("0.00 ms")); } static int Method1(int max1, int max2) { // Inner loop compares against 0 and decrements. int result = 0; for (int i = 0; i < max1; i++) { for (int a = max2 - 1; a >= 0; --a) { if (result++ > 1000) { result = 0; } } } return result; } static int Method2(int max1, int max2) { // Inner loop compares against max int and increments. int result = 0; for (int i = 0; i < max1; i++) { for (int a = 0; a < max2; a++) { if (result++ > 1000) { result = 0; } } } return result; } } Output 556.88 ms Decrement, test against 0 558.37 ms Increment, test against max int

Break.

This stops a loop. It can be used with any kind of loop—it may be more useful in "while" loops. No further iterations are processed.Break

Continue.

This stops the current iteration of a loop—it is like a "goto" to the end of the current loop block. The loop does not terminate.Continue

Goto.

This transfers control to an offset. With goto we can go to enclosing, but not enclosed, blocks. Goto is often considered a poor choice in programs.Goto

Parallel.For.

If the for-loop is not complex enough for you, try Parallel.For. This can perform a task many times faster, but we must use a separate method, and avoid data dependencies.Parallel.For

While versus for.

Is the end point known? In a for-loop we usually go from a known point to another known point. A while-loop is better when no end is yet known.While

A summary.

The for-loop is powerful and easy to write. It is many developers' loop of choice. It makes a C# program feel more like the old times when developers were writing C code.
Home
Dot Net Perls
© 2007-2019 Sam Allen. All rights reserved. Written by Sam Allen, info@dotnetperls.com.