Home
C#
foreach Loop Examples
This page was last reviewed on Nov 10, 2023.
Dot Net Perls
Foreach. Programs spend most of their time in loops. In C#, we find the foreach-loop, which has special features, and clearer syntax.
Shows a reverse loop
With this loop, we evaluate each element individually—an index is not needed. With no indexes, loops are simpler. This makes programs easier to read and understand.
A foreach-loop. Foreach accesses each element in order—this is called enumeration. We eliminate errors caused by incorrect index handling.
Step 1 We create a string array with 3 elements—each the name of a common pet.
Array
Step 2 We use foreach to loop through the elements in the array. Each element can be accessed with the identifier ("value") we choose.
Step 3 Inside the loop, we access the current string element. Foreach returns each element in order.
using System; // Step 1: create an array of 3 strings. string[] pets = { "dog", "cat", "bird" }; // Step 2: loop with the foreach keyword. foreach (string value in pets) { // Step 3: access the enumeration variable. Console.WriteLine("FOREACH ITEM: " + value); }
FOREACH ITEM: dog FOREACH ITEM: cat FOREACH ITEM: bird
Reverse. To use a reverse foreach-loop, we can call Reverse(). We can then use foreach over the reversed results. Reverse() is an extension method—make sure to include System.Linq.
Extension
Info Reverse() receives an IEnumerable collection. IEnumerable is implemented by things like arrays and Lists.
Shows a reverse loop
using System; using System.Linq; // An example array. string[] array = { "bird", "frog", "dog", "snake" }; // Use the Reverse generic extension method. foreach (string value in array.Reverse()) { Console.WriteLine("REVERSE VALUE: " + value); }
REVERSE VALUE: snake REVERSE VALUE: dog REVERSE VALUE: frog REVERSE VALUE: bird
Query. This example uses a foreach-loop to evaluate a LINQ expression. The expression sorts an array. Foreach causes a query to be evaluated.
Step 1 We create an array of 4 strings that are not sorted in any logical order.
Step 2 We specify a query expression. We use orderby to sort the strings. This expression is not evaluated yet—it is lazy.
Step 3 With foreach, we evaluate the lazy query expression from step 2, and print each string. They are sorted alphabetically.
using System; using System.Linq; // Step 1: an unsorted string array. string[] letters = { "d", "c", "a", "b" }; // Step 2: use query to sort the array alphabetically. var sorted = from letter in letters orderby letter select letter; // Step 3: loop with the foreach keyword. foreach (string value in sorted) { Console.WriteLine(value); }
a b c d
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.
yield
Here We call the X() method in the foreach-loop in Main. Inside X(), an infinite sequence of numbers is returned by yield return.
Tip With yield return, the function X "yields." And then control flow returns to the same iteration when X() is called again.
using System; using System.Collections.Generic; public class Program { static void Main() { foreach (int value in X()) { Console.WriteLine(value); // Break at value 10. if (value == 10) { break; } } } static IEnumerable<int> X() { // Return infinite numbers. int i = 0; while (true) { i++; yield return i; } } }
1 2 3 4 5 6 7 8 9 10
Var, implicit types. The var keyword can simplify our loop syntax. The example enumerates a Dictionary. The character count in "KeyValuePair" can be reduced.
Dictionary
KeyValuePair
Here The foreach-loop uses var in its opening statement. The variable (var) is of type KeyValuePair(int, int).
using System; using System.Collections.Generic; // Add items to Dictionary. var data = new Dictionary<int, int>(); data.Add(1, 2); data.Add(2, 3); data.Add(3, 4); // Use var in foreach-loop. foreach (var pair in data) { Console.WriteLine("KEY, VALUE: {0}, {1}", pair.Key, pair.Value); }
KEY, VALUE: 1, 2 KEY, VALUE: 2, 3 KEY, VALUE: 3, 4
List exception. The foreach loop has a drawback. It restricts any mutations made to the collection during the loop. This can impact code that uses Lists.
foreach List
Here We use the foreach-loop over each element in the List. We then try calling the Remove() method.
And The Remove() call fails because of a restriction of the foreach-loop. To add or remove elements inside a loop, consider a for-loop.
for
InvalidOperationException
using System; using System.Collections.Generic; 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); }
1 2 3 Collection was modified; enumeration operation may not execute.
Loop comparison. 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.
using System; // Array of color strings. string[] colors = { "red", "orange", "yellow", "green" }; // Print all colors with for-loop. Console.WriteLine(":::FOR:::"); for (int i = 0; i < colors.Length; i++) { // Assign string reference based on induction variable. string value = colors[i]; Console.WriteLine(value); } // Print all colors with foreach. Console.WriteLine(":::FOREACH:::"); foreach (var value in colors) { Console.WriteLine(value); }
:::FOR::: red orange yellow green :::FOREACH::: red orange yellow green
Error, cannot assign. We cannot assign the variable we use in a foreach-loop. To fix this error, we can add another local inside the loop—that local can be reassigned as much as we want.
Detail If we need to change data in a loop, a for-loop is often a better choice. With for, we can directly assign elements.
class Program { static void Main() { foreach (int value in new int[] { 1, 2, 3 }) { value = 20; } } }
Error CS1656 Cannot assign to 'value' because it is a 'foreach iteration variable'
Error, cannot operate. We cannot use a foreach statement on many kinds of variables such as tuples. An implementation of GetEnumerator (or IEnumerable) is always required.
using System; class Program { static void Main() { var tuple = new Tuple<int, int>(0, 0); // Cannot use foreach on tuple. foreach (int value in tuple) { } } }
Error CS1579 foreach statement cannot operate on variables of type 'Tuple<int, int>' because 'Tuple<int, int>' does not contain a public instance definition for 'GetEnumerator'
Error, cannot convert type. When we specify the variable type in foreach, there must exist a conversion to it. Here the string "test" returns chars.
And A char cannot be converted to a string implicitly (with no cast) so we get an error.
Tip To fix this program, change the string keyword in "foreach" to char (or int, which has a conversion from a char).
class Program { static void Main() { string test = "bird"; // The foreach variable must have a conversion. foreach (string value in test) { } } }
Error CS0030 Cannot convert type 'char' to 'string'
Benchmark, local array. How can we improve the iteration performance of a foreach-loop? The foreach-loop is often less efficient than a simple for-loop.
Version 1 This version of the code uses a foreach-loop that directly accesses the instance field _values.
Version 2 This code stores the instance field into a local variable reference. Then it uses the local in a foreach-loop.
Result The for-loop and foreach have the same performance in 2021 on .NET 5 running on Linux. We should just choose the clearest loop.
using System; using System.Diagnostics; class Program { 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; } const int _max = 100000000; static void Main() { Program program = new Program(); // Version 1: use foreach-loop on field. var s1 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { program.Method1(); program.Method1(); } s1.Stop(); // Version 2: use foreach-loop on local. var s2 = Stopwatch.StartNew(); for (int i = 0; i < _max; i++) { program.Method2(); 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")); } }
6.77 ns: foreach, field 6.72 ns: foreach, local variable
Summary. Foreach is a powerful and elegant loop. It uses the "in" keyword and reads like a sentence—and reduces possible bugs. It handles arrays and works well with queries.
Dot Net Perls is a collection of tested code examples. Pages are continually updated to stay current, with code correctness a top priority.
Sam Allen is passionate about computer languages. In the past, his work has been recommended by Apple and Microsoft and he has studied computers at a selective university in the United States.
This page was last updated on Nov 10, 2023 (simplify).
Home
Changes
© 2007-2024 Sam Allen.