| 

.NET C# Java Javascript Exception

3
Ich bin vor kurzem auf das keyword yield aufmerksam geworden.

Es sammelt Werte in ein IEnumerable und gibt diese dann zurück.

public IEnumerable GetOdd()
{
for(int i = 0; i < 100; i++){
if (i % 2 != 0)
yield return i;
}


Meine Frage lautet: Kennt jemand einen Anwendungszweck der mehr als syntactic sugar ist?
News:
10.09.2009
qwertz 107 1 2 4
2 Antworten
4
yield return ist wie du festgesellt hast "Syntactic Sugar" und erlaubt es auf einfache weise Iterationen zu implementieren.

Du kannst dir mal mit dem Reflektor anschauen wie viel Code der Compiler aus dem yield generiert. Dabei wirst du feststellen dass es eine gute Idee war yield in die Sprache einzuführen.

Die Anwendungszwecke haben sich seit Einführung von LINQ verringert denn seither sind Iterationen nicht mehr so oft explizit zu programmieren.
LINQ verwendet jedoch intern yield sehr häufig (eigentlich immer) - ist im Reflektor aber nicht sichtbar denn der Compiler hat dafür ja Code generiert.

Ein konkreter Anwendungsfall für yield ist wenn eine eigene Methode als Rückgabewert IEnumerable<T> haben soll.
public IEnumerable<string> ReadLines(string fileName)
{
using (StreamReader sr = new StreamReader(fileName))
{
while (!sr.EndOfStream)
yield return sr.ReadLine();
}
}
10.09.2009
gfoidl 9,4k 3 5
Welchen Vorteil hat es effektiv im vergleich zu "var lines = new List<String>()"? 2 mehr/weniger im Vergleich zu deinem Beispiel wird doch nicht die Ursache sein?
Floyd 10.09.2009
1) Dein Snippet erfüllt nicht dem was mein Beispiel zeigt - es ist nur eine Deklaration und somit kann ich den Vorteil/Nachteil nicht bewerten da es nicht vergleichbar ist ;)

2) In meinem Beispiel werden aus einer Datei die Zeilen gelesen. Diese werden nicht alle auf einmal in den RAM gelesen sondern zeilenweise. Stell dir eine Datei mit 1e6 Zeilen vor (oder sonst etwas was nicht in den RAM passt). Da kommst du um so etwas nicht rum.
gfoidl 10.09.2009
4
Ein wirklich sinnvoller Anwendungszweck für yield ist dann gegeben, wenn du nicht nur einen Zustand eines Aufrufs behalten willst, sondern einen ganzen Aufrufstack. Willst du beispielsweise alle Knoten eines Binärbaumes In-Order Ausgeben, dann geht das mit
public IEnumerable<string> readInOrder()
{
foreach(string s in leftChild.readInOrder())
yield return s;
yield return myValue;
foreach(string s in rightChild.readInOrder())
yield return s;
}

(Mit der Warnung von Donald E. Knuth: Beware of bugs in the above code; I have only proved it correct, not tried it.)
10.09.2009
Michri 236 2
1
Dem stimme ich zu. Der Jammer ist eigentlich mehr, dass C# nicht allgemein Koroutinen bekommen hat, sondern nur ein (Einbahnstraßen-)yield für den speziellen Anwendungszweck, die Programmierung von Iteratoren zu vereinfachen.
pjacobi 10.09.2009

Stelle deine .net-Frage jetzt!
TOP TECHNOLOGIES CONSULTING GmbH