Verwenden von Iteratoren (C#-Programmierhandbuch)

Die am häufigsten verwendete Vorgehensweise zum Erstellen eines Iterators ist die Implementierung der GetEnumerator-Methode für die IEnumerable-Schnittstelle. Beispiel:

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

Durch das Vorhandensein der GetEnumerator-Methode wird der Typ ein IEnumerable-Typ, der die Verwendung der foreach-Anweisung ermöglicht. Angenommen, die obige Methode gehört einer Klassendefinition für ListClass an. Dann können Sie foreach für die Klasse wie folgt verwenden:

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
}

Die foreach-Anweisung ruft ListClass.GetEnumerator() auf und verwendet den zurückgegebenen Enumerator, um die Werte zu durchlaufen. Unter Gewusst wie: Erstellen von Iteratorblöcken für generische Listen (C#-Programmierhandbuch) finden Sie ein Beispiel, in dem veranschaulicht wird, wie ein generischer Iterator erstellt wird, der eine IEnumerator<T>-Schnittstelle zurückgibt.

Um zu unterstützen, dass dieselbe Datenauflistung auf mehrere Arten durchlaufen werden kann, können Sie auch benannte Iteratoren verwenden. Sie können beispielsweise einen Iterator bereitstellen, der die Elemente in aufsteigender Reihenfolge zurückgibt, und einen weiteren, der die Elemente in absteigender Reihenfolge zurückgibt. Ein Iterator kann auch über Parameter verfügen, die es Clients ermöglichen, das Iterationsverhalten ganz oder teilweise zu steuern. Der folgende Iterator implementiert die IEnumerable-Schnittstelle mit dem benannten Iterator SampleIterator:

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

So wird der benannte Iterator aufgerufen:

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

Sie können in einem Iterator mehr als eine yield-Anweisung verwenden. Beispiel:

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

Sie können die Ergebnisse anschließend mit der folgenden foreach-Anweisung ausgeben:

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

Durch dieses Beispiel wird folgender Text angezeigt:

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

Bei jedem Durchlauf der foreach-Schleife (oder dem direkten Aufruf von IEnumerator.MoveNext) setzt der nächste Iteratorcodeabschnitt hinter der vorherigen yield-Anweisung auf und setzt die Arbeit fort, bis das Ende des Iteratorabschnitts erreicht ist oder eine yield break-Anweisung gefunden wird.

Iteratoren unterstützen die IEnumerator.Reset-Methode nicht. Zum erneuten Durchlaufen ab dem Anfang müssen Sie einen neuen Iterator abrufen.

Beispiel

Der folgende Code enthält alle Beispiele aus diesem Thema.

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 ".";
        }
    }
}

Siehe auch

Aufgaben

Gewusst wie: Erstellen eines Iteratorblocks für eine Liste ganzer Zahlen (C#-Programmierhandbuch)

Gewusst wie: Erstellen von Iteratorblöcken für generische Listen (C#-Programmierhandbuch)

Referenz

yield (C#-Referenz)

Verwenden von foreach mit Arrays (C#-Programmierhandbuch)

foreach, in (C#-Referenz)

Konzepte

C#-Programmierhandbuch