Export (0) Print
Expand All
11 out of 17 rated this helpful - Rate this topic

8.8.4 The foreach statement

Visual Studio .NET 2003

The foreach statement enumerates the elements of a collection, executing an embedded statement for each element of the collection.

foreach-statement:
foreach   (   type   identifier   in   expression   )   embedded-statement

The type and identifier of a foreach statement declare the iteration variable of the statement. The iteration variable corresponds to a read-only local variable with a scope that extends over the embedded statement. During execution of a foreach statement, the iteration variable represents the collection element for which an iteration is currently being performed. A compile-time error occurs if the embedded statement attempts to modify the iteration variable (by assignment or the ++ and -- operators) or pass the iteration variable as a ref or out parameter.

The type of the expression of a foreach statement must be a collection type (as defined below), and an explicit conversion (Section 6.2) must exist from the element type of the collection to the type of the iteration variable. If expression has the value null, a System.NullReferenceException is thrown.

A type C is said to be a collection type if it implements the System.Collections.IEnumerable interface or implements the collection pattern by meeting all of the following criteria:

  • C contains a public instance method with the signature GetEnumerator() that returns a struct-type, class-type, or interface-type, which is called E in the following text.
  • E contains a public instance method with the signature MoveNext() and the return type bool.
  • E contains a public instance property named Current that permits reading the current value. The type of this property is said to be the element type of the collection type.

A type that implements IEnumerable is also a collection type, even if it does not satisfy the conditions above. (This is possible if it implements some of the IEnumerable members by means of explicit interface member implementation, as described in Section 13.4.1.)

The System.Array type (Section 12.1.1) is a collection type, and since all array types derive from System.Array, any array type expression is permitted in a foreach statement. The order in which foreach traverses the elements of an array is as follows: For single-dimensional arrays, elements are traversed in increasing index order, starting with index 0 and ending with index Length – 1. For multi-dimensional arrays, elements are traversed such that the indices of the rightmost dimension are increased first, then the next left dimension, and so on to the left.

A foreach statement of the form:

foreach (ElementType element in collection) statement

corresponds to one of two possible expansions:

  • If the collection expression is of a type that implements the collection pattern (as defined above), the expansion of the foreach statement is:
    E enumerator = (collection).GetEnumerator();
    try {
       while (enumerator.MoveNext()) {
          ElementType element = (ElementType)enumerator.Current;
          statement;
       }
    }
    finally {
       IDisposable disposable = enumerator as System.IDisposable;
       if (disposable != null) disposable.Dispose();
    }
    

    Significant optimizations of the above are often easily available. If the type E implements System.IDisposable, then the expression (enumerator as System.IDisposable) will always be non-null and the implementation can safely substitute a simple conversion for a possibly more expensive type test. Conversely, if the type E is sealed and does not implement System.IDisposable, then the expression (enumerator as System.IDisposable) will always evaluate to null. In this case, the implementation can safely optimize away the entire finally clause.

  • Otherwise, the collection expression is of a type that implements System.IEnumerable, and the expansion of the foreach statement is:
    IEnumerator enumerator = 
            ((System.Collections.IEnumerable)(collection)).GetEnumerator();
    try {
       while (enumerator.MoveNext()) {
          ElementType element = (ElementType)enumerator.Current;
          statement;
       }
    }
    finally {
       IDisposable disposable = enumerator as System.IDisposable;
       if (disposable != null) disposable.Dispose();
    }
    

In either expansion, the enumerator variable is a temporary variable that is inaccessible in, and invisible to, the embedded statement, and the element variable is read-only in the embedded statement.

The following example prints out each value in a two-dimensional array, in element order:

using System;
class Test
{
   static void Main() {
      double[,] values = {
         {1.2, 2.3, 3.4, 4.5},
         {5.6, 6.7, 7.8, 8.9}
      };
      foreach (double elementValue in values)
         Console.Write("{0} ", elementValue);
      Console.WriteLine();
   }
}

The output produced is as follows:

1.2 2.3 3.4 4.5 5.6 6.7 7.8 8.9
Did you find this helpful?
(1500 characters remaining)
Thank you for your feedback
Show:
© 2014 Microsoft. All rights reserved.