Nach fast 4 Jahren Erfahrung habe ich keinen Code gesehen, in dem das Schlüsselwort yield verwendet wird. Kann mir jemand eine praktische Verwendung (zusammen mit einer Erklärung) dieses Schlüsselworts zeigen, und wenn ja, gibt es keine anderen Möglichkeiten, die Erfüllung der Aufgaben zu erleichtern?
76
yield
nach den allgemeinen Verwendungsmöglichkeiten lautet .Antworten:
Effizienz
Das
yield
Schlüsselwort erstellt effektiv eine verzögerte Aufzählung von Sammlungselementen, die viel effizienter sein kann. Wenn Ihreforeach
Schleife beispielsweise nur die ersten 5 Elemente von 1 Million Elementen durchläuft, ist dies alles einyield
Ergebnis, und Sie haben nicht zuerst intern eine Sammlung von 1 Million Elementen erstellt. Ebenso wollen Sie verwendenyield
mitIEnumerable<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.)
Iterator-Version, effizient
(Es wird keine Zwischensammlung erstellt)
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:
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 aufweisenIEnumerable
,IEnumerator
,IEnumerable<T>
, oderIEnumerator<T>
.) , Und es ist eine besondere Beziehungforeach
. 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 demforeach
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.
quelle
database.Customers.Count()
gesamte Aufzählung der Kunden auf, so dass der effizientere Code erforderlich ist, um alle Elemente durchzugehen?Vor einiger Zeit hatte ich ein praktisches Beispiel. Nehmen wir an, Sie haben eine Situation wie diese:
Das Schaltflächenobjekt kennt seine eigene Position in der Sammlung nicht. Die gleiche Einschränkung gilt für
Dictionary<T>
oder andere Sammlungsarten.Hier ist meine Lösung mit
yield
Schlüsselwort:Und so benutze ich es:
Ich muss
for
meine Sammlung nicht durchlaufen, um den Index zu finden. Mein Button hat eine ID und diese wird auch als Index verwendetIndexerList<T>
, so dass Sie redundante IDs oder Indizes vermeiden - das gefällt mir! Der Index / die ID kann eine beliebige Zahl sein.quelle
Ein praktisches Beispiel finden Sie hier:
http://www.ytechie.com/2009/02/using-c-yield-for-readability-and-performance.html
Die Verwendung von yield bietet gegenüber Standardcode eine Reihe von Vorteilen:
Allerdings, wie Jan_V sagte (schlagen Sie mich nur um ein paar Sekunden :-) Sie können ohne es leben, weil der Compiler intern Code in beiden Fällen fast identisch produzieren wird.
quelle
Hier ist ein Beispiel:
https://bitbucket.org/ant512/workingweek/src/a745d02ba16f/source/WorkingWeek/Week.cs#cl-158
Die Klasse führt Datumsberechnungen basierend auf einer Arbeitswoche durch. Ich kann einer Instanz der Klasse sagen, dass Bob jeden Tag von 9:30 bis 17:30 Uhr mit einer Mittagspause von 12:30 Uhr arbeitet. Mit diesem Wissen liefert die Funktion AscendingShifts () Arbeitsschichtobjekte zwischen den angegebenen Daten. Um alle Arbeitsschichten von Bob zwischen dem 1. Januar und dem 1. Februar dieses Jahres aufzulisten, verwenden Sie sie wie folgt:
Die Klasse durchläuft eine Sammlung nicht wirklich. Die Verschiebungen zwischen zwei Daten können jedoch als Sammlung betrachtet werden. Der
yield
Operator ermöglicht das Durchlaufen dieser imaginären Sammlung, ohne die Sammlung selbst zu erstellen.quelle
Ich habe eine kleine DB-Datenschicht, die eine
command
Klasse hat, in der Sie den SQL-Befehlstext, den Befehlstyp und eine IEnumerable von "Befehlsparametern" zurückgeben.Grundsätzlich besteht die Idee darin, CLR-Befehle einzugeben, anstatt
SqlCommand
Eigenschaften und Parameter ständig manuell auszufüllen .Es gibt also eine Funktion, die so aussieht:
Die Klasse, die diese
command
Klasse erbt , hat die EigenschaftenAge
undName
.Dann können Sie ein
command
Objekt neu anlegen, dessen Eigenschaften gefüllt sind, und es an einedb
Schnittstelle übergeben, die den Befehlsaufruf tatsächlich ausführt.Alles in allem ist es wirklich einfach, mit SQL-Befehlen zu arbeiten und sie zu tippen.
quelle
Obwohl der Zusammenführungsfall bereits in der akzeptierten Antwort behandelt wurde, zeige ich Ihnen die Erweiterungsmethode für Yield-Merge-Parameter ™:
Ich benutze dies, um Pakete eines Netzwerkprotokolls zu erstellen:
Die
MarkChecksum
Methode sieht zum Beispiel so aus. Und es hat auch eineyield
:Seien Sie jedoch vorsichtig, wenn Sie Aggregatmethoden wie Sum () in einer Aufzählungsmethode verwenden, da diese einen separaten Aufzählungsprozess auslösen.
quelle
Elastic Search .NET-Beispiel-Repository bietet ein hervorragendes Beispiel für die
yield return
Partitionierung einer Sammlung in mehrere Sammlungen mit einer bestimmten Größe:https://github.com/elastic/elasticsearch-net-example/blob/master/src/NuSearch.Domain/Extensions/PartitionExtension.cs
quelle
Um auf die Antwort von Jan_V einzugehen, bin ich auf einen konkreten Fall gestoßen, der damit zusammenhängt:
Ich musste die Kernel32-Versionen von FindFirstFile / FindNextFile verwenden. Sie erhalten ein Handle vom ersten Aufruf und geben es an alle nachfolgenden Aufrufe weiter. Wenn Sie dies in einen Enumerator packen, erhalten Sie etwas, das Sie direkt mit foreach verwenden können.
quelle