Condividi tramite


Utilizzo di iteratori (Guida per programmatori C#)

Per creare un iteratore, viene in genere implementato il metodo GetEnumerator sull'interfaccia IEnumerable, ad esempio:

public System.Collections.IEnumerator GetEnumerator()
{
    for (int i = 0; i < 10; i++)
    {
        yield return i;
    }
}

La presenza del metodo GetEnumerator rende il tipo enumerabile e consente l'utilizzo dell'istruzione foreach. Se il metodo precedente fosse incluso in una definizione di classe per ListClass, sarebbe possibile utilizzare foreach sulla classe nel modo seguente:

static void Main()
{
    ListClass listClass1 = new ListClass();

    foreach (int i in listClass1)
    {
        System.Console.Write(i + " ");
    }
    // Output: 0 1 2 3 4 5 6 7 8 9
}

L'istruzione foreach richiama ListClass.GetEnumerator() e utilizza l'enumeratore restituito per scorrere i valori. Per un esempio su come creare un iteratore generico che restituisce un'interfaccia IEnumerator<T>, vedere Procedura: creare un blocco iteratore per un elenco generico (Guida per programmatori C#).

È inoltre possibile utilizzare iteratori denominati per supportare modalità differenti di iterazione sullo stesso insieme di dati. È ad esempio possibile fornire un iteratore che restituisce gli elementi in ordine crescente e uno che li restituisce in ordine decrescente. Un iteratore può inoltre comprendere parametri che consentono ai client di controllare completamente o in parte il comportamento dell'iterazione. L'iteratore riportato di seguito implementa l'interfaccia IEnumerable utilizzando l'iteratore denominato SampleIterator:

// Implementing the enumerable pattern
public System.Collections.IEnumerable SampleIterator(int start, int end)
{
    for (int i = start; i <= end; i++)
    {
        yield return i;
    }
}

L'iteratore denominato viene richiamato nel modo seguente:

ListClass test = new ListClass();

foreach (int n in test.SampleIterator(1, 10))
{
    System.Console.Write(n + " ");
}
// Output: 1 2 3 4 5 6 7 8 9 10

È possibile utilizzare più di una istruzione yield nell'iteratore, come riportato nel seguente esempio:

public System.Collections.IEnumerator GetEnumerator()
{
    yield return "With an iterator, ";
    yield return "more than one ";
    yield return "value can be returned";
    yield return ".";
}

È quindi possibile stampare i risultati utilizzando la seguente istruzione foreach:

foreach (string element in new TestClass())
{
    System.Console.Write(element);
}
// Output: With an iterator, more than one value can be returned.

In questo esempio viene visualizzato il seguente testo:

With an iterator, more than one value can be returned.

A ciascuna successiva iterazione del ciclo foreach (o alla chiamata diretta a IEnumerator.MoveNext), il successivo corpo del codice dell'iteratore riprende dopo la precedente istruzione yield e continua con la successiva fino alla fine del corpo dell'iteratore oppure fino a quando non incontra un'istruzione yield break.

Gli iteratori non supportano il metodo IEnumerator.Reset. Per reiterare dall'inizio è necessario ottenere un nuovo iteratore.

Esempio

Nel codice seguente sono inclusi tutti gli esempi di questo argomento.

namespace UsingIterators
{
    class Program
    {
        static void Main()
        {
            // Using a simple iterator.
            ListClass listClass1 = new ListClass();

            foreach (int i in listClass1)
            {
                System.Console.Write(i + " ");
            }
            // Output: 0 1 2 3 4 5 6 7 8 9
            System.Console.WriteLine();


            // Using a named iterator.
            ListClass test = new ListClass();

            foreach (int n in test.SampleIterator(1, 10))
            {
                System.Console.Write(n + " ");
            }
            // Output: 1 2 3 4 5 6 7 8 9 10
            System.Console.WriteLine();


            // Using multiple yield statements.
            foreach (string element in new TestClass())
            {
                System.Console.Write(element);
            }
            // Output: With an iterator, more than one value can be returned.
            System.Console.WriteLine();

        }
    }

    class ListClass : System.Collections.IEnumerable
    {

        public System.Collections.IEnumerator GetEnumerator()
        {
            for (int i = 0; i < 10; i++)
            {
                yield return i;
            }
        }

        // Implementing the enumerable pattern
        public System.Collections.IEnumerable SampleIterator(int start, int end)
        {
            for (int i = start; i <= end; i++)
            {
                yield return i;
            }
        }
    }

    class TestClass : System.Collections.IEnumerable
    {
        public System.Collections.IEnumerator GetEnumerator()
        {
            yield return "With an iterator, ";
            yield return "more than one ";
            yield return "value can be returned";
            yield return ".";
        }
    }
}

Vedere anche

Attività

Procedura: creare un blocco iteratore per un elenco di valori integer (Guida per programmatori C#)

Procedura: creare un blocco iteratore per un elenco generico (Guida per programmatori C#)

Riferimenti

yield (Riferimenti per C#)

Utilizzo di foreach con matrici (Guida per programmatori C#)

foreach, in (Riferimenti per C#)

Concetti

Guida per programmatori C#