You have a collection in your C# program, such as an array of elements or a generic collection. Use the foreach-loop in the C# programming language to loop over the elements in this reference variable, providing a powerful and simple way to enumerate the individual values with less complex syntax than the traditional for-loop. Here we look at how you can use the foreach-loop in your C# programs, combining it with an array of data and LINQ expressions, and then compare it to the for-loop construct and note compile-time errors.
First, this example shows how you can use the keyword foreach on a string array in a C# program to loop through the elements in the array. In the foreach-statement, you do not need to specify the loop bounds minimum or maximum, and do not need an 'i' variable as in for-loops. This results in fewer characters to type and code that it is easier to review and verify, with no functionality loss.
--- Program that uses foreach over array (C#) ---
using System;
class Program
{
static void Main()
{
// Use a string array to loop over.
string[] ferns = { "Psilotopsida", "Equisetopsida", "Marattiopsida", "Polypodiopsida" };
// Loop with the foreach keyword.
foreach (string value in ferns)
{
Console.WriteLine(value);
}
}
}
--- Output of the program ---
Psilotopsida
Equisetopsida
Marattiopsida
PolypodiopsidaForeach-loop syntax. The foreach-statement contains the reserved "foreach" keyword followed by a parenthetical containing the declaration of the iteration variable. The iteration variable "string value" can be a different type such as "int number" if you are looping over that type. You must specify the keyword 'in' and then the object to loop over. You can use a List, Dictionary, ArrayList, custom collections, or any type of array to loop over.
Here we look at an example that also uses the foreach-loop statement but that evaluates a LINQ expression that sorts an array. The LINQ extension to the C# language provides queries that are evaluated lazily, which means that the sorting in the example won't occur until the foreach loop is executed.
--- Program that uses foreach with 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 of the program ---
a
b
c
dQuery expression evaluation. With the LINQ extensions to the C# language, the foreach keyword is critical because it provides a greater level of abstraction over loop enumeration than a for-loop with an induction variable. Trying to use LINQ without the foreach keyword is frustrating and much more difficult.
Here we compare an example loop with the keyword for and an example loop with the keyword foreach. The code that follows illustrates the exact difference between the two loop constructs. You can see that the for-loop has more complexity in its syntax, but this also gives it more power if you want to modify the collection or examine adjacent elements in the array.
~~~ 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++)
{
string value = rabbits[i]; // Assign string reference based on induction variable.
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.
}
}
}Affine and induction variables. Optimizing compilers such as the C# compiler do interesting static analysis on loop variables in for-loops, because the speed of loops is critical in many programs. In compiler theory, an expression that is based on a loop index such as 'i' is called an affine expression and the loop iteration variables are considered induction variables. The compiler then uses strength reduction techniques to transform slow multiplications into fast additions.
(See Dragon Book [Compilers].)
Here we explore a compile-time error that is caused when you try to compile a program that uses a foreach iteration variable in an incorrect way. Foreach variables are essentially read-only variables, and the C# compiler uses static analysis to detect this kind of error before it ever causes a problem in your program. If you want to change the data in a loop, using a for-loop is often a better choice. With a for-loop, you can use the loop induction variable to assign elements directly.
=== Compile-time error with foreach (Visual Studio 2008) === Error 1 Cannot assign to 'value' because it is a 'foreach iteration variable' ...
Here we concentrate on the performance issues with the foreach-loop versus the for-loop. The foreach-loop has at best equivalent but not better performance in regular looping conditions than the for-loop. Sometimes the foreach-loop can be used in a way that you cannot use a for-loop, such as with the yield keyword, which can enhance performance by delaying or avoiding computations. The author suggests you prefer the foreach-loop when writing less important parts of programs, as it reduces the complexity of the notation, but prefer the for-loop for hot loops as a precaution.
Here we check this site for many other examples of how you can use foreach-loops in your C# programs. This site contains examples for many loops over many types of collections, and this next section lists and describes some of the most useful and popular articles on this subject.
Here we note that when you are implementing a collection that is likely to be widely used throughout other code, you can implement the GetEnumerator parameterless instance method to enable the foreach loop to automatically be able to loop over the data in your collection. This is implemented in the framework collections in System.Collections.Generic, for example. The best resource on the GetEnumerator() method the author has found is in a book by Daniel Solis called Illustrated C# 2008 and that book is highly recommended. [Illustrated C# 2008 - Daniel Solis]
Here we mention a powerful feature in the C# language that gives you a way to declare enumerators with a shorthand syntax. This feature is the keyword yield, which is combined with the break and return keywords to provide a way to re-enter a function in its body. The C# compiler generates a lot of code when you use yield. The keyword yield is contextual, which means it is used to provide this function when the compiler thinks that is the program's intention.
Here we looked at several examples of using foreach-loops in the C# programming language, first seeing an example of looping over an array; an example of the foreach-loop with a LINQ expression; a comparison of the for-loop and foreach-loop; and a compile-time error with the foreach-loop. We noted performance issues with the foreach-loop construct, and how it can be implemented on classes and with the yield keyword. Finally, we mentioned compiler theory and how it relates to loop optimization.