C# Foreach

Array Collections File Keyword String .NET Cast Class Compression Data Directive Enum Exception If Interface Lambda LINQ Loop Method Number Process Property Regex Sort StringBuilder Struct Switch Time Windows WPF

Loop

Loops. Statements execute only once as control flow passes over them. Loop constructs manipulate the flow of control. They repeat statements over and over again.


Loop

Many loops. For has well-defined start, end, and step values. It is helpful for looping over defined, known ranges.
While,
and do-while,
continue until they are broken.

ForWhileDo While
Foreach loop construct

Foreach. This is the easiest, least error-prone loop. It is preferred in many program contexts. But we lose some flexibility with it.

Index:Foreach uses no integer index. Instead, it is used on a collection—it returns each element in order.

Tip:This is called enumeration. We eliminate errors caused by incorrect index handling.

Strings:We use foreach, on a string array, to loop through the elements in the array.

String Array
Based on:

.NET 4.5

Program that uses foreach over array: C#

using System;

class Program
{
    static void Main()
    {
	string[] pets = { "dog", "cat", "bird" };

	// ... Loop with the foreach keyword.
	foreach (string value in pets)
	{
	    Console.WriteLine(value);
	}
    }
}

Output

dog
cat
bird
Keyword: keywords direct program behavior

Keywords. Foreach is a reserved keyword. The iteration variable "string value" can be a different type. For example, we can use "int number" when looping over ints.

Tip:We must specify the keyword "in" and the object to loop over. We can use a collection or array.


LINQ: Language Integrated Query

LINQ. This example uses a foreach-loop to evaluate a LINQ expression. The expression sorts an array. The LINQ extension provides queries that are evaluated lazily.

Delay:The sorting in the example won't occur until the foreach-loop is executed.

Note:With the LINQ extensions the foreach keyword is critical. Trying to use LINQ without foreach is frustrating.

Program that LINQ query: C#

using System;
using System.Linq;

class Program
{
    static void Main()
    {
	// An unsorted string array.
	string[] letters = { "d", "c", "a", "b" };
	// Use LINQ query syntax to sort the array alphabetically.
	var sorted = from letter in letters
		     orderby letter
		     select letter;
	// Loop with the foreach keyword.
	foreach (string value in sorted)
	{
	    Console.WriteLine(value);
	}
    }
}

Output

a
b
c
d
Var keyword

Var, implicit types. The var keyword can simplify our loop syntax. Let's compare a foreach-loop with the var keyword used in the enumeration statement, with a standard foreach-loop.

Var

Example:The example enumerates a Dictionary. We see how the character count in "KeyValuePair" can be reduced.

First:The first loop uses var in the foreach loop. The var actually is of type KeyValuePair(int, int).

Second:The second loop is the standard foreach syntax. The enumeration variable is fully specified.

Program that uses var: C#

using System;
using System.Collections.Generic;

class Program
{
    static Dictionary<int, int> _f = new Dictionary<int, int>();

    static void Main()
    {
	// Add items to dictionary.
	_f.Add(1, 2);
	_f.Add(2, 3);
	_f.Add(3, 4);

	// Use var in foreach loop.
	foreach (var pair in _f)
	{
	    Console.WriteLine("{0},{1}", pair.Key, pair.Value);
	}
    }
}

Program version 2: C#

using System;
using System.Collections.Generic;

class Program
{
    static Dictionary<int, int> _h = new Dictionary<int, int>();

    static void Main()
    {
	// Add items to dictionary.
	_h.Add(5, 4);
	_h.Add(4, 3);
	_h.Add(2, 1);

	// Standard foreach loop.
	foreach (KeyValuePair<int, int> pair in _h)
	{
	    Console.WriteLine("{0},{1}", pair.Key, pair.Value);
	}
    }
}
List

List. The foreach construct elegantly loops through list elements. But it has a drawback. It restricts any mutations made to the collection during the loop.

Here:We use the foreach-loop construct to loop over each element in the List variable. All the integers are printed to the screen.

Restriction:We then try calling the Remove method. This fails because of a restriction of the foreach-loop.

Program that uses list, remove: C#

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
	List<int> list = new List<int>();
	list.Add(1);
	list.Add(2);
	list.Add(3);
	// Loop over list elements using foreach-loop.
	foreach (int element in list)
	{
	    Console.WriteLine(element);
	}
	// You can't remove elements in a foreach-loop.
	try
	{
	    foreach (int element in list)
	    {
		list.Remove(element);
	    }
	}
	catch (Exception ex)
	{
	    Console.WriteLine(ex.Message);
	}
    }
}

Output

1
2
3
Collection was modified; enumeration operation may not execute.
Remove

Removing elements. If you want to add or remove elements during a loop, you could use a for-loop construct. But be careful to maintain correct indexes.

InvalidOperationException
Reverse

Reverse. With the LINQ extensions, we can invoke a Reverse() method. We can then use foreach over the reversed results. This is a reversed foreach-loop of sorts.

Foreach, Reverse

For-loop. Let's compare loops. For has more complexity in its syntax. This gives it more power if you want to modify the collection or examine adjacent elements.

Tip:Optimizing compilers analyze loop variables in for-loops. The speed of loops is critical in many programs.

Note:In compiler theory, an expression that is based on a loop index such as "i" is called an affine expression.

Note 2:The compiler then uses strength reduction techniques to transform slow multiplications into fast additions.

Program that uses for-loop and foreach-loop: C#

using System;

class Program
{
    static void Main()
    {
	// Array of rabbits names.
	string[] rabbits =
	{
	    "Forest Rabbit",
	    "Dice's Cottontail",
	    "Brush Rabbit",
	    "San Jose Brush Rabbit"
	};

	// Loop through string array with a for-loop.
	for (int i = 0; i < rabbits.Length; i++)
	{
	    // Assign string reference based on induction variable.
	    string value = rabbits[i];
	    Console.WriteLine(value); // Write the value.
	}

	// Loop through the string array with a foreach-loop.
	foreach (var value in rabbits)
	{
	    Console.WriteLine(value); // Write the value.
	}
    }
}

Output, partial

Forest Rabbit
Dice's Cottontail
Brush Rabbit
San Jose Brush Rabbit....
Exclamation mark

Errors. A compile-time error is caused when you try to compile a program that incorrectly uses a foreach iteration variable. Foreach variables are read-only.

And:The C# compiler detects this kind of error before it ever causes a problem.

Tip:If you want to change the data in a loop, using a for-loop is often a better choice. With it you can directly assign elements.


Collections: List

Arrays, strings. The foreach-loop is versatile.
We use it on strings,
string arrays,
and even DataTables. These are collections that stored as representations in memory.

Loop, String ArrayLoop Over String CharsForeach, DataTableFor-Loop, String
Get

GetEnumerator. When designing a collection that is likely to be widely used in other code, you can implement this method. This enables the foreach-loop.

Dictionary GetEnumerator
Yield keyword

Yield. This feature allows the position in the control flow to be remembered and resumed when the statement finishes. It is implemented in terms of simpler constructs.

YieldYield, 2D Array
Performance

Performance. Compared to for, foreach has at best equivalent performance in typical conditions. Its benefit is not in performance but in syntax.

For, Foreach Comparison

Sometimes:The foreach-loop can be used in a way that you cannot use a for-loop, such as with the yield keyword.

And:This can enhance performance by delaying or avoiding computations. It can also reduce performance.


Question

Benchmark. How can we improve the iteration performance of a foreach-loop? The foreach-loop is often less efficient than a simple for-loop.

Method 1:Uses a foreach-loop that directly accesses the instance field _values.

Method 2:Stores the instance field into a local variable reference. Then it uses that local variable in the foreach-loop.

Result:Because the field's address is resolved each time it is accessed, Method1() is slower. It adds indirection.

Program that tests foreach-loop performance: C#

using System;
using System.Diagnostics;

class Program
{
    const int _max = 100000000;
    static void Main()
    {
	Program program = new Program();
	var s1 = Stopwatch.StartNew();
	for (int i = 0; i < _max; i++)
	{
	    program.Method1();
	}
	s1.Stop();
	var s2 = Stopwatch.StartNew();
	for (int i = 0; i < _max; i++)
	{
	    program.Method2();
	}
	s2.Stop();
	Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000 * 1000) /
	    _max).ToString("0.00 ns"));
	Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000 * 1000) /
	    _max).ToString("0.00 ns"));
	Console.Read();
    }

    int[] _values = { 1, 2, 3 };

    int Method1()
    {
	// Access the field directly in the foreach expression.
	int result = 0;
	foreach (int value in this._values)
	{
	    result += value;
	}
	return result;
    }

    int Method2()
    {
	// Store the field into a local variable and then iterate.
	int result = 0;
	var values = this._values;
	foreach (int value in values)
	{
	    result += value;
	}
	return result;
    }
}

Output

3.86 ns: foreach, field
2.26 ns: foreach, local variable
Break keyword

Statements. Many control statements are used with loops. The break and continue statements can be implemented with equivalent goto statements.

BreakContinueGoto
Semicolon

Empty. The C# language includes an empty statement construct. It is a simple semicolon after nothing. The empty statement counts as a loop body.

Empty Statement
2D array

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.

Array2D Array
Performance optimization

Performance. How can we make loops go faster? Shaving nanoseconds off a program's runtime should always be at the top of our priority list. We try code tuning loops.

1. Decrement:This applies only to loops with indexes, like for-loops or while-loops or more complex foreach-loops.

Decrement Loops

2. Jam:Jam is a popular food. But when we jam loops, we combine them to reduce iterations in them.

Jam Loops

3. Unwind:Do we really need a loop at all? Why not just unwind the loop statements?

Unwind Loops
Squares: grey

Spaghetti code. Loops help improve code that is hard to follow due to its complex flow control (often called spaghetti code). Loops impart structure to code.

Spaghetti CodeLoop, Two Variables
Squares: grey

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

i Variable
Method

Extract method. Breaking methods with nested loops into multiple methods (as with "Extract Method") is helpful. Code review, testing and good commenting skills are even more useful.

Visual StudioComment

A review. We saw examples of foreach-loops. We discovered how to loop over an array. Then we used the foreach-loop with a LINQ expression.


Loops are wonderful. Many loops exist, but we focused on foreach. We compared it with its boring friend the "for" loop. And we caused a compile-time error.

C#