C# yield: Schritt-für-Schritt-Tutorial zu faulen Sammlungen

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Warum brauchen Sie yield in C#? Das Geheimnis der faulen Sammlungen



Stellen Sie sich vor: Sie schreiben eine Methode, die eine Liste von Zahlen von 1 bis einer Million zurückgeben soll. Das Erste, was einem in den Sinn kommt, ist eine List<int> zu erstellen, sie zu füllen und zurückzugeben. Aber was, wenn der aufrufende Code nur die ersten 10 Elemente haben möchte? Sie haben trotzdem Zeit für die Erstellung von einer Million Objekten aufgewendet, Speicher belegt – und das alles umsonst.



Hier kommt das Schlüsselwort yield in C# ins Spiel. Es ist nicht nur syntaktischer Zucker, sondern ein mächtiges Werkzeug zur Erstellung von faulen (lazy) Sequenzen. In diesem Artikel werden wir yield return und yield break anhand von realen Beispielen analysieren, verstehen, wie sie unter der Haube funktionieren, und lernen, sie in der täglichen Entwicklung anzuwenden.



Dieses Tutorial basiert auf einer echten Frage auf Stack Overflow, die tausende von Aufrufen gesammelt hat. Wir haben es für Bildungsinhalte angepasst und Schritt-für-Schritt-Codebeispiele in C# sowie nützliche praktische Tipps hinzugefügt.



Was ist yield in C#? Einfach erklärt



yield ist ein kontextabhängiges Schlüsselwort in C#, das dem Compiler mitteilt: „Diese Methode ist ein Iterator“. Wenn Sie yield return schreiben, führt die Methode nicht alles auf einmal aus. Stattdessen gibt sie die Elemente einzeln zurück, wenn der aufrufende Code sie anfordert. Dies wird als faule Ausführung bezeichnet.



Im Gegensatz zu einem normalen return, das die Methode beendet, pausiert yield return die Methode, merkt sich ihren Zustand und gibt das aktuelle Element zurück. Beim nächsten Aufruf setzt die Methode ihre Arbeit an der Stelle fort, an der sie angehalten wurde.



Syntax: yield return und yield break



In C# gibt es zwei Formen von yield:



  • yield return – gibt das nächste Element der Sequenz zurück.
  • yield break – beendet die Iteration sofort (wie break in einer Schleife).


Eine Methode, die yield verwendet, muss einen dieser Typen zurückgeben:

  • IEnumerable<T>
  • IEnumerable
  • IAsyncEnumerable<T> (ab C# 8.0)
  • IEnumerator<T> oder IEnumerator


Erstes Beispiel: Vom Einfachen zum Komplexen



Schreiben wir einen einfachen Iterator, der Zahlen von 1 bis 5 generiert:



public static IEnumerable<int> GetNumbers(){    yield return 1;    yield return 2;    yield return 3;    yield return 4;    yield return 5;}

// Verwendung:foreach (int number in GetNumbers()){ Console.WriteLine(number);}


Ausgabe:

12345


Auf den ersten Blick ähnelt dies einer normalen Liste. Aber der Unterschied ist enorm: Jedes Element wird nur dann generiert, wenn es von foreach angefordert wird. Keine Speicherzuweisung für die gesamte Liste!



Wie funktioniert das unter der Haube?



Der C#-Compiler verwandelt die Methode mit yield in einen vollwertigen endlichen Automaten (state machine). Er erstellt eine Klasse, die IEnumerable<T> und IEnumerator<T> implementiert. Diese Klasse speichert:

  • Den aktuellen Zustand (bei welcher Zeile der Methode wir angehalten haben).
  • Lokale Variablen der Methode.
  • Eine Referenz auf das aktuelle Objekt (this), falls die Methode nicht statisch ist.


Jedes Mal, wenn MoveNext() aufgerufen wird (was foreach tut), setzt der endliche Automat die Ausführung an der Stelle des letzten Stopps fort.



Reales Beispiel: Lesen einer großen Datei



Stellen Sie sich vor, Sie müssen eine Logdatei mit einer Größe von 10 GB verarbeiten. Wenn Sie sie vollständig in den Speicher lesen, stürzt das Programm mit einem OutOfMemoryException ab. Mit yield können Sie die Datei zeilenweise lesen und jede Zeile im laufenden Betrieb verarbeiten:



public static IEnumerable<s                

Blogs

Buchempfehlungen