foreach, in (Riferimenti per C#)foreach, in (C# reference)

L' foreach istruzione esegue un'istruzione o un blocco di istruzioni per ogni elemento in un'istanza del tipo che implementa l' System.Collections.IEnumerable System.Collections.Generic.IEnumerable<T> interfaccia o, come illustrato nell'esempio seguente:The foreach statement executes a statement or a block of statements for each element in an instance of the type that implements the System.Collections.IEnumerable or System.Collections.Generic.IEnumerable<T> interface, as the following example shows:

var fibNumbers = new List<int> { 0, 1, 1, 2, 3, 5, 8, 13 };
int count = 0;
foreach (int element in fibNumbers)
{
    Console.WriteLine($"Element #{count}: {element}");
    count++;
}
Console.WriteLine($"Number of elements: {count}");

L' foreach istruzione non è limitata a tali tipi.The foreach statement isn't limited to those types. È possibile usarlo con un'istanza di qualsiasi tipo che soddisfi le condizioni seguenti:You can use it with an instance of any type that satisfies the following conditions:

  • Un tipo ha il metodo pubblico senza parametri il GetEnumerator cui tipo restituito è una classe, uno struct o un tipo di interfaccia.A type has the public parameterless GetEnumerator method whose return type is either class, struct, or interface type. A partire da C# 9,0, il GetEnumerator metodo può essere un metodo di estensionedel tipo.Beginning with C# 9.0, the GetEnumerator method can be a type's extension method.
  • Il tipo restituito del GetEnumerator metodo ha la proprietà Public Current e il metodo pubblico senza parametri il MoveNext cui tipo restituito è Boolean .The return type of the GetEnumerator method has the public Current property and the public parameterless MoveNext method whose return type is Boolean.

Nell'esempio seguente viene utilizzata l' foreach istruzione con un'istanza del System.Span<T> tipo, che non implementa alcuna interfaccia:The following example uses the foreach statement with an instance of the System.Span<T> type, which doesn't implement any interfaces:

public class IterateSpanExample
{
    public static void Main()
    {
        Span<int> numbers = new int[] { 3, 14, 15, 92, 6 };
        foreach (int number in numbers)
        {
            Console.Write($"{number} ");
        }
        Console.WriteLine();
    }
}

A partire da C# 7,3, se la proprietà dell'enumeratore Current restituisce un valore restituito di riferimento ( ref T dove T è il tipo di un elemento della raccolta), è possibile dichiarare una variabile di iterazione con il ref ref readonly modificatore o, come illustrato nell'esempio seguente:Beginning with C# 7.3, if the enumerator's Current property returns a reference return value (ref T where T is the type of a collection element), you can declare an iteration variable with the ref or ref readonly modifier, as the following example shows:

public class ForeachRefExample
{
    public static void Main()
    {
        Span<int> storage = stackalloc int[10];
        int num = 0;
        foreach (ref int item in storage)
        {
            item = num++;
        }

        foreach (ref readonly var item in storage)
        {
            Console.Write($"{item} ");
        }
        // Output:
        // 0 1 2 3 4 5 6 7 8 9
    }
}

A partire da C# 8,0, è possibile usare l' await foreach istruzione per utilizzare un flusso asincrono di dati, ovvero il tipo di raccolta che implementa l' IAsyncEnumerable<T> interfaccia.Beginning with C# 8.0, you can use the await foreach statement to consume an asynchronous stream of data, that is, the collection type that implements the IAsyncEnumerable<T> interface. Ogni iterazione del ciclo può essere sospesa mentre l'elemento successivo viene recuperato in modo asincrono.Each iteration of the loop may be suspended while the next element is retrieved asynchronously. Nell'esempio seguente viene illustrato come utilizzare l' await foreach istruzione:The following example shows how to use the await foreach statement:

await foreach (var item in GenerateSequenceAsync())
{
    Console.WriteLine(item);
}

Per impostazione predefinita, gli elementi del flusso vengono elaborati nel contesto acquisito.By default, stream elements are processed in the captured context. Se si desidera disabilitare l'acquisizione del contesto, utilizzare il TaskAsyncEnumerableExtensions.ConfigureAwait metodo di estensione.If you want to disable capturing of the context, use the TaskAsyncEnumerableExtensions.ConfigureAwait extension method. Per ulteriori informazioni sui contesti di sincronizzazione e sull'acquisizione del contesto corrente, vedere utilizzo del modello asincrono basato su attività.For more information about synchronization contexts and capturing the current context, see Consuming the Task-based asynchronous pattern. Per ulteriori informazioni sui flussi asincroni, vedere la sezione relativa ai flussi asincroni nell'articolo novità di C# 8,0 .For more information about asynchronous streams, see the Asynchronous streams section of the What's new in C# 8.0 article.

In un punto qualsiasi all'interno del blocco dell'istruzione foreach è possibile uscire dal ciclo usando l'istruzione break o passare all'iterazione successiva nel ciclo con l'istruzione continue.At any point within the foreach statement block, you can break out of the loop by using the break statement, or step to the next iteration in the loop by using the continue statement. È anche possibile uscire foreach da un ciclo tramite le istruzioni goto, returno throw .You can also exit a foreach loop by the goto, return, or throw statements.

Se l'istruzione foreach viene applicata a null, viene generata una NullReferenceException.If the foreach statement is applied to null, a NullReferenceException is thrown. Se la raccolta di origine dell' foreach istruzione è vuota, il corpo del foreach ciclo non viene eseguito e ignorato.If the source collection of the foreach statement is empty, the body of the foreach loop isn't executed and skipped.

Tipo di una variabile di iterazioneType of an iteration variable

È possibile usare la var parola chiave per consentire al compilatore di dedurre il tipo di una variabile di iterazione nell' foreach istruzione, come illustrato nel codice seguente:You can use the var keyword to let the compiler infer the type of an iteration variable in the foreach statement, as the following code shows:

foreach (var item in collection) { }

È anche possibile specificare in modo esplicito il tipo di una variabile di iterazione, come illustrato nel codice seguente:You can also explicitly specify the type of an iteration variable, as the following code shows:

IEnumerable<T> collection = new T[5];
foreach (V item in collection) { }

Nel form precedente, il tipo T di un elemento della raccolta deve essere convertibile in modo implicito o esplicito nel tipo V di una variabile di iterazione.In the preceding form, type T of a collection element must be implicitly or explicitly convertible to type V of an iteration variable. Se una conversione esplicita da T a V non riesce in fase di esecuzione, l' foreach istruzione genera un'eccezione InvalidCastException .If an explicit conversion from T to V fails at run time, the foreach statement throws an InvalidCastException. Se, ad esempio, T è un tipo di classe non sealed, V può essere qualsiasi tipo di interfaccia, anche quello che T non implementa.For example, if T is a non-sealed class type, V can be any interface type, even the one that T doesn't implement. In fase di esecuzione, il tipo di un elemento della raccolta può essere quello che deriva da T e implementa effettivamente V .At run time, the type of a collection element may be the one that derives from T and actually implements V. In caso contrario, InvalidCastException viene generata un'eccezione.If that's not the case, an InvalidCastException is thrown.

Specifiche del linguaggio C#C# language specification

Per altre informazioni, vedere la sezione L'istruzione foreach della specifica del linguaggio C#.For more information, see The foreach statement section of the C# language specification.

Per ulteriori informazioni sulle funzionalità aggiunte in C# 8,0 e versioni successive, vedere le note della proposta di funzionalità seguenti:For more information about features added in C# 8.0 and later, see the following feature proposal notes:

Vedere ancheSee also