In der MSDN-Dokumentation wird dies jedoch erwähnt, jedoch nicht erläutert. Das ist ein schlechter Weg, um einen wissenshungrigen Entwickler zu ärgern.
Phil
3
Die Ertragsrendite macht eine Sicherungsliste überflüssig, dh Sie müssen nicht so etwas wie MyList.Add(...)einfach tun codieren yield return .... Wenn Sie vorzeitig aus der Schleife ausbrechen und die von Ihnen verwendete virtuelle Hintergrundliste zurückgeben müssenyield break;
The Muffin Man
Antworten:
529
Es gibt an, dass ein Iterator beendet wurde. Sie können sich yield breakeine returnAnweisung vorstellen, die keinen Wert zurückgibt.
Wenn Sie beispielsweise eine Funktion als Iterator definieren, sieht der Funktionskörper möglicherweise folgendermaßen aus:
for(int i =0; i <5; i++){yieldreturn i;}Console.Out.WriteLine("You will see me");
Beachten Sie, dass nach Abschluss aller Zyklen der Schleife die letzte Zeile ausgeführt wird und die Meldung in Ihrer Konsolen-App angezeigt wird.
Oder so mit yield break:
int i =0;while(true){if(i <5){yieldreturn i;}else{// note that i++ will not be executed after thisyieldbreak;}
i++;}Console.Out.WriteLine("Won't see me");
In diesem Fall wird die letzte Anweisung nie ausgeführt, da wir die Funktion vorzeitig verlassen haben.
Könnte es einfach breakstatt yield breakin Ihrem obigen Beispiel sein? Der Compiler beschwert sich nicht darüber.
Orad
85
@orad a simple würde breakin diesem Fall die Schleife stoppen, aber die Methodenausführung nicht abbrechen, sodass die letzte Zeile ausgeführt würde und der Text "Ich sehe mich nicht" tatsächlich angezeigt würde.
Damir Zekić
5
@Damir Zekić Können Sie Ihrer Antwort auch hinzufügen, warum Sie eine Renditeunterbrechung der Rendite vorziehen sollten und was die Unterschiede zu beiden sind?
Bruno Costa
11
@ DamirZekić gibt null zurück und Yield Break ist nicht dasselbe. Wenn Sie null zurückgeben, können Sie NullReferenceExceptionden Enumerator von IEnumerable abrufen, während Sie dies bei Yield Break nicht tun (es gibt eine Instanz ohne Elemente).
Bruno Costa
6
@BrunoCosta Der Versuch, regelmäßige Rückgaben in derselben Methode zu erzielen, führt zu einem Compilerfehler. Wenn Sie yield return xden Compiler mit Warnungen versehen, soll diese Methode syntaktischer Zucker zum Erstellen eines EnumeratorObjekts sein. Dieser Enumerator verfügt über Methode MoveNext()und Eigenschaft Current. MoveNext () führt die Methode bis zu einer yield returnAnweisung aus und wandelt diesen Wert in um Current. Beim nächsten Aufruf von MoveNext wird die Ausführung von dort aus fortgesetzt. yield breaksetzt Current auf null und signalisiert das Ende dieses Enumerators, so dass a foreach (var x in myEnum())endet.
Wolfzoon
57
Beendet einen Iteratorblock (z. B. sagt, dass die IEnumerable keine weiteren Elemente enthält).
mit [+1] - obwohl es akademisch keine Iteratoren in .NET gibt. nur Aufzähler (eine Richtung, vorwärts.)
Shaun Wilson
@Shaun Wilson, aber mit yieldSchlüsselwort können Sie Sammlung in beide Richtungen iterieren, außerdem können Sie jedes nächste Element der Sammlung nicht in einer Reihe nehmen
monstr
@monstr Sie können die Sammlung auf jede Art und Weise iterieren und müssen es nicht yieldtun. Ich sage nicht, dass Sie falsch liegen, ich sehe, was Sie vorschlagen; Akademisch gesehen gibt es in .NET jedoch keine Iteratoren, nur Enumeratoren (eine Richtung, vorwärts) - im Gegensatz zu stdc ++ ist in der CTS / CLR kein "generisches Iterator-Framework" definiert. LINQ hilft dabei, die Lücke mit Erweiterungsmethoden zu schließen, die yield returnauch Rückrufmethoden verwenden. Es handelt sich jedoch um erstklassige Erweiterungsmethoden, nicht um erstklassige Iteratoren. Das Ergebnis IEnumerablekann selbst nicht in eine andere Richtung als die Weiterleitung an den Anrufer iterieren.
Shaun Wilson
29
Sagt dem Iterator, dass das Ende erreicht ist.
Als Beispiel:
publicinterfaceINode{IEnumerable<Node>GetChildren();}publicclassNodeWithTenChildren:INode{privateNode[] m_children =newNode[10];publicIEnumerable<Node>GetChildren(){for(int n =0; n <10;++n ){yieldreturn m_children[ n ];}}}publicclassNodeWithNoChildren:INode{publicIEnumerable<Node>GetChildren(){yieldbreak;}}
yieldGrundsätzlich IEnumerable<T>verhält sich eine Methode ähnlich wie ein kooperativ (im Gegensatz zu präventiv) geplanter Thread.
yield returnist wie ein Thread, der eine "Zeitplan" - oder "Ruhe" -Funktion aufruft, um die Kontrolle über die CPU aufzugeben. Genau wie bei einem Thread IEnumerable<T>erhält die Methode unmittelbar danach die Steuerelemente zurück, wobei alle lokalen Variablen dieselben Werte haben wie vor der Aufgabe der Steuerung.
yield break ist wie ein Faden, der das Ende seiner Funktion erreicht und endet.
Die Leute sprechen von einer "Zustandsmaschine", aber eine Zustandsmaschine ist alles, was ein "Faden" wirklich ist. Ein Thread hat einen bestimmten Status (dh Werte lokaler Variablen), und jedes Mal, wenn er geplant ist, werden einige Aktionen ausgeführt, um einen neuen Status zu erreichen. Der entscheidende Punkt yieldist, dass im Gegensatz zu den gewohnten Betriebssystem-Threads der Code, der ihn verwendet, rechtzeitig eingefroren wird, bis die Iteration manuell erweitert oder beendet wird.
Du hast mir gerade eine Kopie verkauft. Vielen Dank! :-)
Jon Schneider
9
Die yield breakAnweisung bewirkt, dass die Aufzählung gestoppt wird. Tatsächlich yield breakschließt die Aufzählung ohne zusätzliche Einzelteile zurückbringen.
Bedenken Sie, dass es tatsächlich zwei Möglichkeiten gibt, wie eine Iteratormethode die Iteration stoppen kann. In einem Fall könnte die Logik der Methode die Methode natürlich verlassen, nachdem alle Elemente zurückgegeben wurden. Hier ist ein Beispiel:
IEnumerable<uint>FindPrimes(uint startAt,uint maxCount){for(var i =0UL; i < maxCount; i++){
startAt =NextPrime(startAt);yieldreturn startAt;}Debug.WriteLine("All the primes were found.");}
Im obigen Beispiel stoppt die Iteratormethode natürlich die Ausführung, sobald maxCountPrimzahlen gefunden wurden.
Die yield breakAnweisung ist eine weitere Möglichkeit für den Iterator, die Aufzählung einzustellen. Es ist ein Weg, früh aus der Aufzählung auszubrechen. Hier ist die gleiche Methode wie oben. Dieses Mal ist die Zeit begrenzt, die die Methode ausführen kann.
IEnumerable<uint>FindPrimes(uint startAt,uint maxCount,int maxMinutes){var sw =System.Diagnostics.Stopwatch.StartNew();for(var i =0UL; i < maxCount; i++){
startAt =NextPrime(startAt);yieldreturn startAt;if(sw.Elapsed.TotalMinutes> maxMinutes)yieldbreak;}Debug.WriteLine("All the primes were found.");}
Beachten Sie den Anruf an yield break. Tatsächlich wird die Aufzählung vorzeitig beendet.
Beachten Sie auch, dass das yield breakanders funktioniert als nur eine Ebene break. Beendet im obigen Beispiel yield breakdie Methode, ohne den Aufruf von zu tätigen Debug.WriteLine(..).
public static IEnumerable <int> Bereich (int min, int max)
{
während (wahr)
{
if (min> = max)
{
Ertragsbruch;
}}
Yield Return min ++;
}}
}}
und Erklärung, dass, wenn eine yield breakAnweisung innerhalb einer Methode getroffen wird, die Ausführung dieser Methode ohne Rückgabe stoppt. Es gibt einige Zeitsituationen, in denen Sie keine Ertragsunterbrechung verwenden können, wenn Sie kein Ergebnis liefern möchten.
Nun, sie sind nur kompliziert, wenn Sie sich für den Code interessieren, in den sie kompiliert wurden. Code, der sie verwendet, ist ziemlich einfach.
Robert Rossney
@ Robert, das habe ich gemeint, also habe ich die Antwort aktualisiert, um Ihren Kommentar aufzunehmen
Tony Lee
-2
Das Schlüsselwort yield wird zusammen mit dem Schlüsselwort return verwendet, um dem Enumerator-Objekt einen Wert bereitzustellen. Yield Return gibt den oder die zurückgegebenen Werte an. Wenn die Renditeerklärung erreicht ist, wird der aktuelle Standort gespeichert. Die Ausführung wird an dieser Stelle beim nächsten Aufruf des Iterators neu gestartet.
So erklären Sie die Bedeutung anhand eines Beispiels:
Wenn dies wiederholt wird, werden folgende Werte zurückgegeben: 0, 2, 5.
Es ist wichtig zu beachten , dass Zähler Variable in diesem Beispiel eine lokale Variable ist. Nach der zweiten Iteration, die den Wert 2 zurückgibt, beginnt die dritte Iteration an der Stelle, an der sie zuvor verlassen wurde, wobei der vorherige Wert der lokalen Variablen mit dem Namen counter beibehalten wird, der 2 war.
Ich glaube nicht, dass yield returndie Rückgabe mehrerer Werte unterstützt wird. Vielleicht haben Sie das eigentlich nicht gemeint, aber so habe ich es gelesen.
Sam
Sam - Die SampleNumbers-Methode mit mehreren Yield-Return-Anweisungen funktioniert tatsächlich. Der Wert des Iterators wird sofort zurückgegeben und die Ausführung wird fortgesetzt, wenn der nächste Wert angefordert wird. Ich habe gesehen, wie Leute eine Methode wie diese mit "Yield Break" beendet haben, aber es ist unnötig. Wenn Sie das Ende der Methode erreichen, endet auch der Iterator
Loren Paulsen
Der Grund dafür ist, yield breakdass es keinen Enumerator auf Sprachebene wie a enthält. foreachWenn Sie einen Enumerator verwenden, yield breakliefert dieser einen echten Wert. Dieses Beispiel sieht aus wie eine abgewickelte Schleife. Sie werden diesen Code fast nie in der realen Welt sehen (wir können uns alle einige Randfälle vorstellen, klar), auch hier gibt es keinen "Iterator". Der "Iteratorblock" kann aus sprachlichen Gründen nicht über die Methode hinausgehen. Was tatsächlich zurückgegeben wird, ist eine "Aufzählung", siehe auch: stackoverflow.com/questions/742497/…
MyList.Add(...)
einfach tun codierenyield return ...
. Wenn Sie vorzeitig aus der Schleife ausbrechen und die von Ihnen verwendete virtuelle Hintergrundliste zurückgeben müssenyield break;
Antworten:
Es gibt an, dass ein Iterator beendet wurde. Sie können sich
yield break
einereturn
Anweisung vorstellen, die keinen Wert zurückgibt.Wenn Sie beispielsweise eine Funktion als Iterator definieren, sieht der Funktionskörper möglicherweise folgendermaßen aus:
Beachten Sie, dass nach Abschluss aller Zyklen der Schleife die letzte Zeile ausgeführt wird und die Meldung in Ihrer Konsolen-App angezeigt wird.
Oder so mit
yield break
:In diesem Fall wird die letzte Anweisung nie ausgeführt, da wir die Funktion vorzeitig verlassen haben.
quelle
break
stattyield break
in Ihrem obigen Beispiel sein? Der Compiler beschwert sich nicht darüber.break
in diesem Fall die Schleife stoppen, aber die Methodenausführung nicht abbrechen, sodass die letzte Zeile ausgeführt würde und der Text "Ich sehe mich nicht" tatsächlich angezeigt würde.NullReferenceException
den Enumerator von IEnumerable abrufen, während Sie dies bei Yield Break nicht tun (es gibt eine Instanz ohne Elemente).yield return x
den Compiler mit Warnungen versehen, soll diese Methode syntaktischer Zucker zum Erstellen einesEnumerator
Objekts sein. Dieser Enumerator verfügt über MethodeMoveNext()
und EigenschaftCurrent
. MoveNext () führt die Methode bis zu eineryield return
Anweisung aus und wandelt diesen Wert in umCurrent
. Beim nächsten Aufruf von MoveNext wird die Ausführung von dort aus fortgesetzt.yield break
setzt Current auf null und signalisiert das Ende dieses Enumerators, so dass aforeach (var x in myEnum())
endet.Beendet einen Iteratorblock (z. B. sagt, dass die IEnumerable keine weiteren Elemente enthält).
quelle
yield
Schlüsselwort können Sie Sammlung in beide Richtungen iterieren, außerdem können Sie jedes nächste Element der Sammlung nicht in einer Reihe nehmenyield
tun. Ich sage nicht, dass Sie falsch liegen, ich sehe, was Sie vorschlagen; Akademisch gesehen gibt es in .NET jedoch keine Iteratoren, nur Enumeratoren (eine Richtung, vorwärts) - im Gegensatz zu stdc ++ ist in der CTS / CLR kein "generisches Iterator-Framework" definiert. LINQ hilft dabei, die Lücke mit Erweiterungsmethoden zu schließen, dieyield return
auch Rückrufmethoden verwenden. Es handelt sich jedoch um erstklassige Erweiterungsmethoden, nicht um erstklassige Iteratoren. Das ErgebnisIEnumerable
kann selbst nicht in eine andere Richtung als die Weiterleitung an den Anrufer iterieren.Sagt dem Iterator, dass das Ende erreicht ist.
Als Beispiel:
quelle
yield
GrundsätzlichIEnumerable<T>
verhält sich eine Methode ähnlich wie ein kooperativ (im Gegensatz zu präventiv) geplanter Thread.yield return
ist wie ein Thread, der eine "Zeitplan" - oder "Ruhe" -Funktion aufruft, um die Kontrolle über die CPU aufzugeben. Genau wie bei einem ThreadIEnumerable<T>
erhält die Methode unmittelbar danach die Steuerelemente zurück, wobei alle lokalen Variablen dieselben Werte haben wie vor der Aufgabe der Steuerung.yield break
ist wie ein Faden, der das Ende seiner Funktion erreicht und endet.Die Leute sprechen von einer "Zustandsmaschine", aber eine Zustandsmaschine ist alles, was ein "Faden" wirklich ist. Ein Thread hat einen bestimmten Status (dh Werte lokaler Variablen), und jedes Mal, wenn er geplant ist, werden einige Aktionen ausgeführt, um einen neuen Status zu erreichen. Der entscheidende Punkt
yield
ist, dass im Gegensatz zu den gewohnten Betriebssystem-Threads der Code, der ihn verwendet, rechtzeitig eingefroren wird, bis die Iteration manuell erweitert oder beendet wird.quelle
Das gesamte Thema der Iteratorblöcke wird in diesem kostenlosen Beispielkapitel aus Jon Skeets Buch C # in Depth ausführlich behandelt .
quelle
Die
yield break
Anweisung bewirkt, dass die Aufzählung gestoppt wird. Tatsächlichyield break
schließt die Aufzählung ohne zusätzliche Einzelteile zurückbringen.Bedenken Sie, dass es tatsächlich zwei Möglichkeiten gibt, wie eine Iteratormethode die Iteration stoppen kann. In einem Fall könnte die Logik der Methode die Methode natürlich verlassen, nachdem alle Elemente zurückgegeben wurden. Hier ist ein Beispiel:
Im obigen Beispiel stoppt die Iteratormethode natürlich die Ausführung, sobald
maxCount
Primzahlen gefunden wurden.Die
yield break
Anweisung ist eine weitere Möglichkeit für den Iterator, die Aufzählung einzustellen. Es ist ein Weg, früh aus der Aufzählung auszubrechen. Hier ist die gleiche Methode wie oben. Dieses Mal ist die Zeit begrenzt, die die Methode ausführen kann.Beachten Sie den Anruf an
yield break
. Tatsächlich wird die Aufzählung vorzeitig beendet.Beachten Sie auch, dass das
yield break
anders funktioniert als nur eine Ebenebreak
. Beendet im obigen Beispielyield break
die Methode, ohne den Aufruf von zu tätigenDebug.WriteLine(..)
.quelle
Hier ist http://www.alteridem.net/2007/08/22/the-yield-statement-in-c/ ein sehr gutes Beispiel:
und Erklärung, dass, wenn eine
yield break
Anweisung innerhalb einer Methode getroffen wird, die Ausführung dieser Methode ohne Rückgabe stoppt. Es gibt einige Zeitsituationen, in denen Sie keine Ertragsunterbrechung verwenden können, wenn Sie kein Ergebnis liefern möchten.quelle
Yield Break ist nur eine Möglichkeit, zum letzten Mal Return zu sagen und keinen Wert zurückzugeben
z.B
quelle
Wenn Sie unter "Was bewirkt Ertragsunterbrechung wirklich?" Meinen, "wie funktioniert es?" - Weitere Informationen finden Sie im Blog von Raymond Chen unter https://devblogs.microsoft.com/oldnewthing/20080812-00/?p=21273
C # -Iteratoren generieren sehr komplizierten Code.
quelle
Das Schlüsselwort yield wird zusammen mit dem Schlüsselwort return verwendet, um dem Enumerator-Objekt einen Wert bereitzustellen. Yield Return gibt den oder die zurückgegebenen Werte an. Wenn die Renditeerklärung erreicht ist, wird der aktuelle Standort gespeichert. Die Ausführung wird an dieser Stelle beim nächsten Aufruf des Iterators neu gestartet.
So erklären Sie die Bedeutung anhand eines Beispiels:
Wenn dies wiederholt wird, werden folgende Werte zurückgegeben: 0, 2, 5.
Es ist wichtig zu beachten , dass Zähler Variable in diesem Beispiel eine lokale Variable ist. Nach der zweiten Iteration, die den Wert 2 zurückgibt, beginnt die dritte Iteration an der Stelle, an der sie zuvor verlassen wurde, wobei der vorherige Wert der lokalen Variablen mit dem Namen counter beibehalten wird, der 2 war.
quelle
yield break
tutyield return
die Rückgabe mehrerer Werte unterstützt wird. Vielleicht haben Sie das eigentlich nicht gemeint, aber so habe ich es gelesen.yield break
dass es keinen Enumerator auf Sprachebene wie a enthält.foreach
Wenn Sie einen Enumerator verwenden,yield break
liefert dieser einen echten Wert. Dieses Beispiel sieht aus wie eine abgewickelte Schleife. Sie werden diesen Code fast nie in der realen Welt sehen (wir können uns alle einige Randfälle vorstellen, klar), auch hier gibt es keinen "Iterator". Der "Iteratorblock" kann aus sprachlichen Gründen nicht über die Methode hinausgehen. Was tatsächlich zurückgegeben wird, ist eine "Aufzählung", siehe auch: stackoverflow.com/questions/742497/…