1. Funktionen implementiert durch Yield
Ertragsrendite:
Schauen wir uns den folgenden Code an, der eine Funktion implementiert, die dem Durchqueren eines Arrays mit foreach durch Yield Return ähnelt und darauf hinweist, dass Yield Return auch zur Implementierung der Funktion des Iterators verwendet wird.
Yield Break:
Betrachtet man den untenstehenden Code, werden nur 1 und 2 ausgegeben, aber nicht 3, was darauf hindeutet, dass der Iterator durch Yield Break gestoppt wurde, sodass Yield Break zur Termination der Iteration verwendet wird.
2. Sie kann nur in <T><T>Methoden, Operatoren oder Get-Accessoren verwendet werden, die einen IEnumerable, IEnumerable, IEnumerator oder IEnumerator zurückgeben müssen.
3. Das Implementierungsprinzip des Yield-Schlüsselworts
Wir haben die foreach-Schleife durch eine while-Schleife ersetzt und festgestellt, dass wir zwar weder GetEnumerator() noch die entsprechenden Eigenschaften MoveNext() und Current des IEnumerator implementiert haben, aber dennoch mit diesen Funktionen arbeiteten.
Warum das so ist: Wir können ILSpy verwenden, um die generierte exe zu dekompilieren, um den Grund zu finden.
Da die direkte Dekompilierung zu C# so wird, wie sie ist,
Deshalb haben wir uns entschieden, es in IL-Code mit C#-Annotationen zu dekompilieren, obwohl die Lesbarkeit schlecht ist, aber wir können die Prinzipien im Detail verstehen. Schauen wir uns zunächst die Übersetzung des Programms an: Während der Kompilierung wird automatisch eine neue Klasse generiert.
Schauen wir uns den Code genauer an, und EnumerableFuc() gibt diese neue Klasse zurück.
Wenn wir uns die Implementierung der Klasse ansehen, die dieser Code automatisch generiert, sehen wir, dass sie IEnumerable<T>, IEnumerable, IEnumerator oder IEnumerator erbt, und wir <T>sollten vermuten können, dass diese neue Klasse der Grund ist, warum wir die entsprechenden Eigenschaften MoveNext() und Current des IEnumerator nicht implementieren, aber wir können diese Funktionen weiterhin normal verwenden.
Schauen wir uns an, wie diese Klasse iteriert, schauen wir uns hauptsächlich die MoveNext()-Funktion an
Jeder Aufruf der MoveNext()-Funktion addiert 1 zum Zustand, und es werden insgesamt 4 Iterationen durchgeführt, wobei die ersten drei true und die letzte false zurückgeben, was das Ende der Iteration bedeutet. Diese vier Iterationen entsprechen den Anweisungen in enumberableFuc(), die in 4 Teile durch 3 Yield-Return-Anweisungen unterteilt sind.
Der eigentliche Prozess der Iteration mit enumberableFuc() ist:
1. Führe die Funktion enumberableFuc() aus, um eine Instanz der Klasse zu erhalten, die automatisch vom Code generiert wird. 2. Dann rufen Sie die Funktion GetEnumberator() auf, um mit der Iteration der erworbenen Klasse selbst als Iterator zu beginnen. 3. Jedes Mal, wenn du MoveNext() ausführst, steigt der Zustand um 1, und die Switch-Anweisung erlaubt es dir, verschiedene Teile des Codes auszuführen, jedes Mal, wenn du MoveNext() aufrufst. 4。 MoveNext() gibt false zurück, endet. Dies zeigt auch, dass das Yield-Schlüsselwort tatsächlich ein syntaktischer Zucker ist und letztlich eine iterative Funktion ist, die durch die Implementierung von IEnumberable<T>, IEnumberable, <T>IEnumberator und IEnumberator-Schnittstellen implementiert wird.
|