Share via


yield (C#-Referenz)

Wenn Sie das yield-Schlüsselwort in einer Anweisung verwenden, geben Sie damit an, dass die Methode, der Operator oder der get-Accessor, in dem es vorkommt, ein Iterator ist. Wird ein Iterator mithilfe von yield definiert, ist eine explizite zusätzliche Klasse (die Klasse, die den Zustand für eine Enumeration enthält, siehe beispielsweise IEnumerator) nicht erforderlich, wenn Sie das IEnumerable-Muster und das IEnumerator-Muster für einen benutzerdefinierten Auflistungstyp implementieren.

Im folgenden Beispiel werden zwei Formen der yield-Anweisung gezeigt.

yield return <expression>;
yield break;

Hinweise

Sie verwenden eine yield return-Anweisung, um jedes Element einzeln zurückzugeben.

Sie erzeugen eine Iteratormethode, indem Sie eine foreach-Anweisung oder eine LINQ-Abfrage verwenden. Jede Iteration der foreach-Schleife ruft die Iteratormethode auf. Wenn eine yield return-Anweisung im Iterator erreicht wird, wird ein expression-Ausdruck zurückgegeben, und die aktuelle Position im Code wird beibehalten. Wenn die Iteratorfunktion das nächste Mal aufgerufen wird, wird die Ausführung von dieser Position neu gestartet.

Sie verwenden eine yield break-Anweisung, um die Iteration zu beenden.

Weitere Informationen zu Iteratoren finden Sie unter Iteratoren (C# und Visual Basic).

Iteratormethoden und get-Accessoren

Die Deklaration eines Iterators muss die folgenden Anforderungen erfüllen:

Der yield-Typ eines Iterators, der IEnumerable oder IEnumerator zurückgibt, ist object. Wenn der Iterator IEnumerable oder IEnumerator zurückgibt, ist eine implizite Konvertierung vom Typ des Ausdrucks in der yield return-Anweisung in den generischen Typparameter erforderlich.

Sie können keine yield return- oder yield break-Anweisung in Methoden einbeziehen, die die folgenden Eigenschaften aufweisen:

Ausnahmebehandlung

Eine yield return-Anweisung kann sich nicht in einem try-catch-Block befinden. Eine yield return-Anweisung kann sich im try-Block einer try-finally-Anweisung befinden.

Eine yield break-Anweisung kann sich in einem try- oder catch-Block befinden, nicht jedoch in einem finally-Block.

Wenn der foreach-Text (außerhalb der Iteratormethode) eine Ausnahme auslöst, wird ein finally-Block in der Iteratormethode ausgeführt.

Technische Implementierung

Der folgende Code gibt einen IEnumerable<string> aus einer Iteratormethode zurück und durchläuft dann die Elemente.

IEnumerable<string> elements = MyIteratorMethod();
foreach (string element in elements)
{
   …
}

Der Aufruf von MyIteratorMethod führt nicht den Text der Methode aus. Stattdessen gibt der Aufruf einen IEnumerable<string> in die Variable elements zurück.

Bei einer Iteration der foreach-Schleife wird die Methode MoveNext für elements aufgerufen. Dieser Aufruf führt MyIteratorMethod aus, bis die nächste yield return-Anweisung erreicht ist. Der Ausdruck, der durch die yield return-Anweisung zurückgegeben wird, ermittelt nicht nur den Wert der element-Variable für die Verwendung im Schleifentext, sondern auch die Current-Eigenschaft der Elemente, die IEnumerable<string> ist.

Bei jeder nachfolgenden Iteration der foreach-Schleife wird die Ausführung des Iteratortexts da fortgesetzt, wo sie beendet wurde, und endet dann wieder an einer yield return-Anweisung. Die foreach-Schleife wird beendet, wenn das Ende der Iteratormethode oder eine yield break-Anweisung erreicht wird.

Beispiel

Das folgende Beispiel weist eine yield return-Anweisung auf, die sich innerhalb einer for-Schleife befindet. Jede Iteration des foreach-Anweisungstexts in Process erzeugt einen Aufruf an die Power-Iteratorfunktion. Jeder Aufruf der Iteratorfunktion führt bei der nächsten Iteration der for-Schleife zur nächsten Ausführung der yield return-Anweisung.

Der Rückgabetyp der Iteratormethode ist IEnumerable, was ein Iteratorschnittstellentyp ist. Wird die Iteratormethode aufgerufen wird, gibt sie ein aufzählbares Objekt zurück, das die Potenzen einer Zahl enthält.

public class PowersOf2
{
    static void Main()
    {
        // Display powers of 2 up to the exponent of 8: 
        foreach (int i in Power(2, 8))
        {
            Console.Write("{0} ", i);
        }
    }

    public static System.Collections.Generic.IEnumerable<int> Power(int number, int exponent)
    {
        int result = 1;

        for (int i = 0; i < exponent; i++)
        {
            result = result * number;
            yield return result;
        }
    }

    // Output: 2 4 8 16 32 64 128 256
}

Das folgende Beispiel zeigt einen get-Accessor, der ein Iterator ist. Im Beispiel gibt jede yield return-Anweisung eine Instanz einer benutzerdefinierten Klasse zurück.

public static class GalaxyClass
{
    public static void ShowGalaxies()
    {
        var theGalaxies = new Galaxies();
        foreach (Galaxy theGalaxy in theGalaxies.NextGalaxy)
        {
            Debug.WriteLine(theGalaxy.Name + " " + theGalaxy.MegaLightYears.ToString());
        }
    }

    public class Galaxies
    {

        public System.Collections.Generic.IEnumerable<Galaxy> NextGalaxy
        {
            get
            {
                yield return new Galaxy { Name = "Tadpole", MegaLightYears = 400 };
                yield return new Galaxy { Name = "Pinwheel", MegaLightYears = 25 };
                yield return new Galaxy { Name = "Milky Way", MegaLightYears = 0 };
                yield return new Galaxy { Name = "Andromeda", MegaLightYears = 3 };
            }
        }

    }

    public class Galaxy
    {
        public String Name { get; set; }
        public int MegaLightYears { get; set; }
    }
}

C#-Programmiersprachenspezifikation

Weitere Informationen erhalten Sie unter C#-Sprachspezifikation. Die Sprachspezifikation ist die verbindliche Quelle für die Syntax und Verwendung von C#.

Siehe auch

Referenz

foreach, in (C#-Referenz)

Konzepte

C#-Programmierhandbuch

Weitere Ressourcen

C#-Referenz

Iteratoren (C# und Visual Basic)