5.2. The for Statement#

The for statement executes a statement or a block of statements while a specified Boolean expression evaluates to true. Such evaluation involves comparing the local loop counter variable (an integer counter that increments/decrements over every loop) to a preset value. Since the number of loops is controlled by comparing the counter with the preset value, you need to specify the preset value to decide the number of times you want to run the code block when defining a for loop statement.

5.2.1. For Statement Syntax#

for loops are usually favored for iteration because the all the information about the local loop variable are available in one place at the top, which helps quickly visualize the overall sequence in the loop.

The C# for loop statement syntax is:

for ( *initializer* ; *condition* ; *iterator* )
{
// code block (statements)
}

Let us practice in csharprepl or VS Code:

for (int i = 1; i <= 5; i++)
{
      Console.WriteLine(i);
}

You can see that the for loop has four parts, a three-section semicolon-separated header and a body:

  • Initializer: This section is a variable declaration statement that declares a local loop variable (or iterator variable or the counter) and initialize it with an initial value.

  • Condition: The condition section is a boolean expression that determines if the next iteration in the loop should be executed or should the loop be terminated. If it evaluates to true, the next iteration is executed; otherwise, the loop is exited.

  • Iterator: The iterator (iteration expression) section that defines what happens to the counter after each execution of the body of the loop. A common behavior is reassigning (increment or decrement) the value of the counter.

  • The body of the loop, which must be a statement or a block of statements.

In the example above, the initializer is i = 1, condition is i <= n, and iterator is i++ (see arithmetic operators).

Note that the initializer section is executed only once, before entering the loop. Also, the declared variable is local to the for loop heading and the loop body and can not be accessed from outside the for statement.

The two semicolons are always needed in the for heading, but any of the parts they normally separate may be omitted. If the condition part is omitted, the condition is interpreted as always true, leading to an infinite loop, that can only terminate due to a return or break statement in the body.

Header variation

The declaration of a for loop header is flexible. There may be several variables of the same type initialized, separated by commas. Also, at the end of the for loop heading, the iteration portion may include more than one expression, also separated by commas. For example:

for (int i = 0, j = 10; i < j; i = i+2, j++) {
   Console.WriteLine("{0} {1}", i, j);
}

Guess what this does, and then paste it into csharprepl to check.

5.2.1.1. Execution sequence#

For the execution sequence of for loops, note that the different parts of the heading are used at different times:

  • When starting the statement, the initialization is done, and then the test of condition (boolean expression).

  • After finishing the body and returning to the heading, the iteration operations are done, followed by the test.

5.2.2. break and continue Statements#

The basic syntax of the for statement is simplistic. Here we are using the break and continue statements to learn the pragmatic coding practice of the for loops by connecting to our understanding of conditional/selection statements.

When performing iteration, there will be times that you want to alter the code execution sequence by skipping part or all of the iterations. If you only want to break out of the enclosing loop, but not out of the whole method or the outer loop (in case of nested looping), use a break statement

break;

in place of return, since return will break out the current method. With the break statement, execution continues after terminating the enclosing iteration statement.

Note that the break and continue statements only make practical sense inside of an if statement that is inside the loop. In the following examples, you see a for statement with a break statement enclosed in a conditional/selection statement.

Assuming that variable target already has a string value and variable arr is an array of strings. With your knowledge about arr.Length and arr[i] from String (string), read the following code:

bool found = false;

for (int i = 0; i < arr.Length; i++)   // loop for arr.Length times
{
   if (arr[i] == target)               // if one of arr == targe
   {
      found = true;                    // set found to true
      break;                           // break out of the enclosing loop
   }
}

if (found)                             // if found == true (from the previous block)
{
   Console.WriteLine("Target found at index " + i);
}
else
{
   Console.WriteLine("Target not found");
}

When an element in arr is reached that matches target, execution breaks out of the for loop and move on to the if (found) statement block below.

Now, observe an alternate implementation with a compound condition (Compound Boolean Expressions) in the heading and no break is:

 bool found = false;

 for (int i = 0; i < a.Length && !found; i++) {
    if (a[i] == target) {
       found = true;
    }
 }

 if (found) {
    Console.WriteLine("Target found at index " + i);
 } else {
    Console.WriteLine("Target not found");
 }

As you can see, the code exit because the condition section of the if statement header has an expression !found (C# Operator Types), meaning found is not true. The shows that since break statements rely on the logic of the conditional statement, if the condition can be embedded in the header of the loop, you don’t have to use break. However, if you are designing a loop that has multiple exit criteria, using break statements can make the code much less verbose in the header’s condition section, and hence easier to follow because the if statement conditions and the immediate break action may be clearly presented.

5.2.3. Nested for Loop#

There will be times when nested loops are are required for the problem scenario. A nested loop can look like this:

outer-Loop
{
   // body of outer-loop
   inner-Loop
   {
      // body of inner-loop
   }
... ... ...
}

Continuing with our discussion on break, let’s say we are in a situation like the following:

for (....) {

   // some statements of outer for loop

   for (....) {
      ...
      if (...) {
      ...
      break;
      }
      ...
   }

   // some statements of outer for look
}

The break statement is in the inner loop. If it is reached, the inner loop ends, but the inner loop is just a single statement inside the outer loop, and the outer loop continues. If the outer loop continuation condition remains true, the inner loop will be executed again. As an example:

for (int i = 0; i <= 3; i++)
{
   for (int j = 0; j <= 3; j++)
   {

      if (i == 2)
      {
         break;
      }

      Console.WriteLine("{0} -- {1}", i, j);
   }
}

Can you determine the output of the preceding code? Try it in csharprepl or a test project in your tests folder.

continue Statement

For completeness we mention the much less used continue statement:

continue;

A continue statement: - does not break out of the whole loop statement. - break/skips the execution of the rest of the body in the current enclosing loop iteration. - starts the next enclosing loop iteration.

In the simplest situations, a continue statement just avoids an extra else clause. It can considerably shorten code if the test is inside of complicated, deeply nested if statements. As an example:

for (int i = 0; i <= 3; i++)
{
   for (int j = 0; j <= 3; j++)
   {
      if (i == 2)
      {
           continue;
      }

      Console.WriteLine("{0} -- {1}", i, j);
   }
}

Can you determine the output of the preceding code? Try it in csharprepl or a test project in your tests folder.

5.2.4. Additional Loop Step Patterns#

The following examples were moved from 0503-for-examples to keep all for step patterns in one section.

5.2.5. Step in loop header#

i++ is a common pattern and it increments by 1. Also common in the iterator/step section of the loop header is using assignment statement to control stepping:

i = i + k;

or the equivalent short-hand compound assignment operator:

i += k;

This means to increment the variable i by k.

Most C# binary operations have a similar variation. For instance if op is +, -, *, / or %,

variable op= expression

means the same as

variable = variable op expression

For example

x *= 5;

is the same as

x = x * 5;

5.2.6. foreach Essentials#

This short section was consolidated from the previous standalone foreach page.

5.3. foreach Statement#

A C# foreach works like a for loop, except it does not use the header (initializer, condition, and iterator) for conditional looping flow control. Instead, the foreach loop iterates through each element in a given sequence or collection of data and runs a set of instructions once for each of the elements. In other words, the foreach loop is used exclusively to loop through elements in an array (or other data sets).

In the case of for loop in C#, the local loop variable refers to the index of an array whereas, in the case of a foreach loop, the loop variable refers to the values of the array.

In for loop, the loop variable is of type int. The reason for this is, here the loop variable refers to the index position of the array. For the foreach loop, the data type of the loop variable must be the same as the type of the values stored in the array. For example, if you have a string array, then the loop variable must be of type string.

The syntax of the foreach loop is:

foreach (type variableName in arrayName)
{
   // code block to be executed
}

A foreach statement only works with an object that holds a sequence or collection of data. We will see many more kinds of sequences later. For now we can illustrate with a string, which is a sequence of characters. Observe and test the following two pieces of code in csharprepl to see how foreach differs from the for statement.

Say you want to print out some Unicode/ASCII code for certain characters. To achieve that using C# for loop, the code could look like:

> string str = "ABCabc";
> for (int i = 0; i < 6; i++)
  {
      Console.WriteLine("Unicode for {0} is {1}", i, (int)str[i]);
  }
Unicode for 0 is 65
Unicode for 1 is 66
Unicode for 2 is 67
Unicode for 3 is 97
Unicode for 4 is 98
Unicode for 5 is 99

>

As you can see, with a for loop, you refer to the individual characters by its index and then cast it to int:

(int)str[i]

Since strings are considered as arrays consisting of char type characters, we can loop through a string using a foreach statement using type char and cast to print out the underlying int Unicode value of each character. To achieve the same results using the foreach loop, the code would look like the following (pay attention to the local loop variable char ch; type is required as usual):

> string str = "ABCabc";
  foreach (char ch in str) {
     Console.WriteLine("Unicode for {0} is {1}.", ch, (int)ch);
  }
Unicode for A is 65.
Unicode for B is 66.
Unicode for C is 67.
Unicode for a is 97.
Unicode for b is 98.
Unicode for c is 99.

As you can see, in a foreach loop, we do not rely on array indexing to refer to the elements. Instead, we refer to the elements directly with the local loop variable (ch) declared with the type (char in this case).

As you see in the preceding example, the foreach heading feeds us one character from str each time through, using the name ch to refer to it. Since any new variable name must be declared with a type in C#, so ch is preceded in the heading by its type, char. Then we can use ch inside the body of the loop.

``foreach`` vs. for loop

Some of the advantages/disadvantages of foreach over the for loop are:

  • foreach not involve variable setup (iterates over each element of the array).

  • foreach are more concise and readable than the indexing for statement.

The foreach loop does have some limitations: [1]

  • They don’t keep track of the index of the item.

  • They cannot iterate backwards. The loop can only go forward in one step.

  • If you wish to modify the array, the foreach loop isn’t the most suitable option.

  • The foreach loop cannot execute two-decision statements at once.

If you have explicit need to refer to the indices of the items in the sequence, then a foreach statement does not work for you.

5.3.1. break in foreach#

With a foreach loop, which has no explicit continuation condition, the break could be more clearly useful. Here is a variant if you do not care about the specific location of the target:

bool found = false;

foreach (string s in a) {
   if (s == target)
   {
      found = true;
      break;
   }
}

if (found) {
   Console.WriteLine("Target found");
} else {
   Console.WriteLine("Target not found");
}

Note that for the for and foreach loops, you could do all the same things with while loops, which you will learn in subsequent chapters, but there are many situations where foreach loops and for loops are more convenient and easier to read.

{rubric} Footnotes

[1] For a discussion of C# for loop vs foreach loop, see Understanding What Is C# Foreach Loop