Effizienz
Das yield
Schlüsselwort erstellt effektiv eine verzögerte Aufzählung von Sammlungselementen, die viel effizienter sein kann. Wenn Ihre foreach
Schleife beispielsweise nur die ersten 5 Elemente von 1 Million Elementen durchläuft, ist dies alles ein yield
Ergebnis, und Sie haben nicht zuerst intern eine Sammlung von 1 Million Elementen erstellt. Ebenso wollen Sie verwenden yield
mit IEnumerable<T>
Rückgabewerte in der eigenen Programmierung Szenarien die gleichen Wirkungsgrade zu erreichen.
Beispiel für die in einem bestimmten Szenario erzielte Effizienz
Keine Iteratormethode, potenziell ineffiziente Verwendung einer großen Sammlung.
(Die Zwischensammlung besteht aus vielen Elementen.)
// Method returns all million items before anything can loop over them.
List<object> GetAllItems() {
List<object> millionCustomers;
database.LoadMillionCustomerRecords(millionCustomers);
return millionCustomers;
}
// MAIN example ---------------------
// Caller code sample:
int num = 0;
foreach(var itm in GetAllItems()) {
num++;
if (num == 5)
break;
}
// Note: One million items returned, but only 5 used.
Iterator-Version, effizient
(Es wird keine Zwischensammlung erstellt)
// Yields items one at a time as the caller's foreach loop requests them
IEnumerable<object> IterateOverItems() {
for (int i; i < database.Customers.Count(); ++i)
yield return database.Customers[i];
}
// MAIN example ---------------------
// Caller code sample:
int num = 0;
foreach(var itm in IterateOverItems()) {
num++;
if (num == 5)
break;
}
// Note: Only 5 items were yielded and used out of the million.
Vereinfachen Sie einige Programmierszenarien
In einem anderen Fall werden einige Arten des Sortierens und Zusammenführens von Listen einfacher programmiert, da Sie die yield
Elemente nur in der gewünschten Reihenfolge zurücksortieren, anstatt sie in eine Zwischensammlung zu sortieren und dort einzutauschen. Es gibt viele solcher Szenarien.
Nur ein Beispiel ist das Zusammenführen von zwei Listen:
IEnumerable<object> EfficientMerge(List<object> list1, List<object> list2) {
foreach(var o in list1)
yield return o;
foreach(var o in list2)
yield return o;
}
Mit dieser Methode wird eine zusammenhängende Liste von Elementen zurückgegeben, dh eine Zusammenführung, für die keine Zwischensammlung erforderlich ist.
Mehr Info
Das yield
Schlüsselwort kann nur im Zusammenhang mit einem Iterator - Verfahren verwendet werden (einen Rückgabetyp aufweisen IEnumerable
, IEnumerator
, IEnumerable<T>
, oder IEnumerator<T>
.) , Und es ist eine besondere Beziehung foreach
. Iteratoren sind spezielle Methoden. Die MSDN-Ertrags- und Iteratordokumentation enthält viele interessante Informationen und Erläuterungen zu den Konzepten. Korrelieren Sie es unbedingt mit dem foreach
Schlüsselwort, indem Sie es auch lesen, um Ihr Verständnis von Iteratoren zu ergänzen.
Um zu erfahren, wie die Iteratoren ihre Effizienz erreichen, befindet sich das Geheimnis im vom C # -Compiler generierten IL-Code. Die für eine Iteratormethode generierte IL unterscheidet sich drastisch von der für eine reguläre (Nicht-Iterator-) Methode generierten. Dieser Artikel (Was generiert das Yield-Schlüsselwort wirklich?) Bietet diese Art von Einsicht.