Heim >Backend-Entwicklung >C#.Net-Tutorial >C# 2.0-Spezifikation (Iterator) (1)
22 Iteratoren
22.1 Iteratorblöcke
Ein Iteratorblock ist ein Block von Anweisungen, der eine geordnete Folge von Werten erzeugt. Iteratorblöcke unterscheiden sich von regulären Anweisungsblöcken durch eine oder mehrere yield-Anweisungen.
l Die yield return-Anweisung erzeugt den nächsten Wert der Iteration.
l Die yield break-Anweisung zeigt an, dass die Iteration abgeschlossen ist.
Der Iteratorblock kann als Methodenkörper, Operatorkörper oder Zugriffskörper verwendet werden, vorausgesetzt, der Rückgabetyp des entsprechenden Funktionsmitglieds ist ein Enumerator (eine der Enumeratorschnittstellen oder eine der aufzählbaren Schnittstellen).
Der Iteratorblock ist kein eindeutiges Element in der C#-Syntax. Sie sind in mehrfacher Hinsicht eingeschränkt und wirken sich hauptsächlich auf die Semantik von Funktionsmemberdeklarationen aus, syntaktisch gesehen handelt es sich jedoch lediglich um Anweisungsblöcke.
Wenn ein Funktionsmember mithilfe eines Iteratorblocks implementiert wird, führt die Angabe von Ref- oder Out-Parametern für die formale Parameterliste zu einem Fehler bei der Kompilierung.
Eine return-Anweisung innerhalb eines Iteratorblocks verursacht einen Fehler bei der Kompilierung (eine yield return-Anweisung ist jedoch zulässig).
Das Einfügen eines unsicheren Kontexts (§18.1) in einen Iteratorblock führt zu einem Fehler bei der Kompilierung. Auch wenn die Iteratordeklaration in einen unsicheren Kontext eingebettet ist, wird der Iteratorblock immer als sicherer Kontext definiert.
22.1.1 Enumerator-Schnittstelle
Die Enumerator-Schnittstelle (Enumerator-Schnittstelle)[/b] ist die System.Collections.IEnumerator-Schnittstelle und System.Collections.Generic.IEnumerator
22.1.2 Aufzählbare Schnittstelle
Die aufzählbare Schnittstelle (aufzählbare Schnittstelle[/b])[/b] ist die System.Collections.IEnumerable-Schnittstelle und System.Collections.Generic.IEnumerable< Alle Instanzen von ;T>. In diesem Kapitel werden diese Schnittstellen entsprechend als IEnumerable und IEnumerable
22.1.3Ertragstyp
Der Iteratorblock generiert eine Sequenz mit allen Werten desselben Typs. Der angegebene Typ wird als yield[/b]-Typ des Iteratorblocks (yield type[/b])[/b] bezeichnet.
l Der Ertragstyp des Iteratorblocks wird normalerweise zum Implementieren von Funktionsmitgliedern verwendet, die IEnumerator- oder IEnumerable-Objekte zurückgeben.
l Der Yield-Typ des Iteratorblocks wird normalerweise verwendet, um einen Funktionsmember zu implementieren, der IEnumerator
22.1.4 dieser Zugriff
Innerhalb eines Iteratorblocks eines Instanzmitglieds einer Klasse wird dieser Ausdruck als Wert klassifiziert. Der Typ des Werts ist der Klassentyp. Diese Verwendung kann in diesem Typ verwendet werden. Der Wert ist die Referenz auf das Objekt, wenn das Mitglied aufgerufen wird.
Innerhalb eines Iteratorblocks eines Instanzmitglieds einer Struktur wird dies beim Ausdruck als Variable klassifiziert. Der Typ der Variablen ist der Strukturtyp, in dem sie auf diese Weise verwendet werden kann. Diese Variable stellt eine Kopie der entsprechenden Struktur dar, wenn ein Mitglied aufgerufen wird. Innerhalb eines Iteratorblocks eines Strukturinstanzmitglieds verhält sich diese Variable so, als wäre sie ein Wertparameter des Strukturtyps.
22.2 Aufgezählte Objekte
Wenn ein Funktionsmember, der einen Enumerator-Schnittstellentyp zurückgibt, mithilfe eines Iteratorblocks implementiert wird, führt der Aufruf des Funktionsmembers den Code im Iteratorblock nicht sofort aus. Stattdessen wird ein Enumeratorobjekt erstellt und zurückgegeben. Dieses Objekt kapselt den im Iteratorblock angegebenen Code. Wenn die MoveNext-Methode des Enumeratorobjekts aufgerufen wird, wird der Code im Iteratorblock ausgeführt. Enumeratorobjekte weisen die folgenden Eigenschaften auf.
l Es implementiert IEnumerator und IEnumerator
l Es implementiert System.IDisposable.
l Es wird mit einer Kopie des Argumentwerts (falls vorhanden) initialisiert und der Instanzwert wird an das Funktionsmitglied übergeben.
l Es gibt vier mögliche Zustände davor, läuft, ausgesetzt und danach, und es wird vor dem Vorher-Zustand initialisiert.
Das Enumerator-Objekt ist normalerweise eine vom Compiler generierte Enumerator-Klasseninstanz, die den Code im Iterator-Anweisungsblock kapselt und die Enumerator-Schnittstelle implementiert, aber auch andere Implementierungsmethoden sind möglich. Wenn eine Enumeratorklasse vom Compiler generiert wird, wird die Klasse eingebettet, die Klasse verfügt über privaten Zugriff innerhalb der Klasse, die das Funktionsmitglied enthält, und die Klasse verfügt über einen Namen, der für die Verwendung durch den Compiler reserviert ist (§2.4.2).
Enumeratorobjekte können mehr Schnittstellen implementieren als hier angegeben.
In den folgenden Abschnitten wird das genaue Verhalten der MoveNext-, Current- und Dispose-Mitglieder beschrieben, die von den Schnittstellen IEnumerable und IEnumerable
Bitte beachten Sie, dass Enumeratorobjekte die IEnumerator.Reset-Methode nicht unterstützen. Der Aufruf dieser Methode löst eine System.NotSupportedException-Ausnahme aus.
22.2.1MoveNext-Methode
Die MoveNext-Methode des Enumeratorobjekts kapselt den Code des Iteratorblocks. Durch den Aufruf der MoveNext-Methode wird der Code im Iterator ausgeführt und die Current-Eigenschaft des Aufzählungsobjekts auf den entsprechenden Wert gesetzt. Die genaue Aktion, die von der MoveNext-Methode ausgeführt wird, hängt vom Status des Enumeratorobjekts beim Aufruf der MoveNext-Methode ab.
l Wenn der Status des Enumeratorobjekts vorher lautet, ändert der Aufruf von MoveNext
n den Status in „Wird ausgeführt“.
n initialisiert die Parameter des Iteratorblocks (einschließlich dieses) mit den tatsächlichen Parameterwerten und Instanzwerten, die bei der Initialisierung des Enumeratorobjekts gespeichert wurden.
n Führt den Iteratorblock von Anfang an aus, bis die Ausführung unterbrochen wird (wie unten beschrieben).
l Wenn der Status des Enumeratorobjekts „Running“ lautet, ist das Ergebnis des Aufrufs von MoveNext nicht spezifiziert.
l Wenn der Status des Enumeratorobjekts angehalten ist, ändert der Aufruf von MoveNext
n den Status in „Wird ausgeführt“.
l Stellt den Wert aller lokalen Variablen und Parameter (einschließlich dieser) auf den Wert des Ausführungsstatus wieder her, als der Iterator zuletzt angehalten (suspendiert) wurde. Beachten Sie, dass sich der Inhalt aller Objekte, auf die diese Variablen verweisen, seit einem vorherigen Aufruf von MoveNext geändert haben kann.
n Startet die Ausführung des Iteratorblocks nach der yield return-Anweisung, die die Unterbrechung der Ausführung verursacht hat, neu und fährt in diesem Zustand fort, bis die Ausführung unterbrochen wird (unten beschrieben).
l Wenn der Status des Enumeratorobjekts danach ist, gibt der Aufruf von MoveNext false zurück.
Wenn MoveNext einen Iteratorblock ausführt, gibt es vier Möglichkeiten, die Ausführung zu unterbrechen: Durch eine Yield-Return-Anweisung, durch eine Yield-Break-Anweisung wird der Endpunkt des Iteratorblocks erreicht und eine Ausnahme wird ausgelöst und nach außen weitergegeben Iteratorblock.
l Wenn eine Yield-Return-Anweisung (§22.4) angetroffen wird, geschieht Folgendes:
n Der in der Anweisung angegebene Ausdruck wird ausgewertet, implizit in den Yield-Typ konvertiert und der Current-Eigenschaft von zugewiesen das Aufzählungsobjekt.
n Die Ausführung des Iteratorkörpers wird ausgesetzt. Die Werte aller lokalen Variablen und Parameter (einschließlich dieser) werden gespeichert, ebenso wie die Position der yield return-Anweisung. Wenn sich die yield return-Anweisung innerhalb eines oder mehrerer try-Blöcke befindet, wird der zugehörige final-Block zu diesem Zeitpunkt nicht ausgeführt.
n Der Status des Enumeratorobjekts wird in „Angehalten“ geändert.
n Die MoveNext-Methode gibt „true“ an den Aufrufer zurück und zeigt an, dass der Iterator erfolgreich zum nächsten Wert vorgerückt ist.
l Wenn eine yield break-Anweisung angetroffen wird, geschieht Folgendes:
n Wenn sich die yield break-Anweisung innerhalb eines oder mehrerer try-Blöcke befindet, wird die damit verbundene „finally“-Anweisung ausgeführt.
n Der Status des Enumeratorobjekts wird in „After“ geändert.
n MoveNext-Methode gibt „false“ an den Aufrufer zurück und gibt damit an, dass die Iteration abgeschlossen wurde.
l Wenn der Endpunkt des Iteratorblocks erreicht wird, geschieht Folgendes.
n Der Status des Enumeratorobjekts wird in „After“ geändert.
n MoveNext-Methode gibt an den Aufrufer false zurück, was darauf hinweist, dass die Iteration abgeschlossen wurde.
l Wenn eine Ausnahme ausgelöst und außerhalb des Iteratorblocks weitergegeben wird, geschieht Folgendes.
n Innerhalb des Iteratorblocks wird aufgrund der Ausnahmeweitergabe der entsprechende Finalblock ausgeführt.
n Der Status des Enumeratorobjekts wird in „After“ geändert.
n Für den Aufrufer der MoveNext-Methode wird die Ausnahmeweitergabe fortgesetzt.
22.2.2 Current-Eigenschaft
Die Current-Eigenschaft eines Enumeratorobjekts wird durch die yield return-Anweisung des Iteratorblocks beeinflusst.
Wenn sich das Enumeratorobjekt im angehaltenen Zustand befindet, ist der Wert von Current der Wert, der beim letzten Aufruf von MoveNext festgelegt wurde. Wenn sich das Enumeratorobjekt im Status „Vorher“, „Wird ausgeführt“ oder „Nachher“ befindet, sind die Ergebnisse des Zugriffs auf „Aktuell“ nicht spezifiziert.
Für einen Yield-Typ-Iteratorblock mit einem Nicht-Objekttyp entspricht die Implementierung, die durch den Zugriff auf Current über die IEnumerable-Implementierung des Enumeratorobjekts erhalten wird, der Implementierung, die durch den Zugriff auf Current über den IEnumerator
22.2.3 Entsorgungsmethode
Die Dispose-Methode bereinigt die Iterationsergebnisse, indem sie den Status des Enumeratorobjekts auf „after“ setzt.
l Wenn der Status des Enumeratorobjekts „vorher“ ist, ändert der Aufruf von „Dispose“ seinen Status in „nachher“.
l Wenn der Status des Enumeratorobjekts ausgeführt wird, ist das Ergebnis des Aufrufs von Dispose das angegebene.
l Wenn der Status des Enumeratorobjekts angehalten ist, wird der Aufruf von Dispose
n seinen Status in „Läuft“ ändern.
n Führen Sie den „finally“-Block so aus, als ob die zuletzt ausgeführte yield return-Anweisung eine yield break-Anweisung wäre. Wenn hier eine Ausnahme ausgelöst und außerhalb des Iteratorkörpers weitergegeben wird, wird der Status des Enumeratorobjekts auf „after“ gesetzt und die Ausnahme wird an den Aufrufer der Dispose-Methode weitergegeben.
n ändert seinen Status in „Nachher“.
l Wenn der Status des Enumeratorobjekts danach ist, hat der Aufruf von Dispose keine Auswirkung.
22.3 Aufzählbare Objekte
Wenn ein Funktionsmember, der einen aufzählbaren Schnittstellentyp zurückgibt, mithilfe eines Iteratorblocks implementiert wird, führt der Aufruf des Funktionsmembers nicht sofort zur Ausführung des Iteratorblockcodes. Stattdessen wird ein aufzählbares Objekt ([/b]aufzählbares Objekt[/b])[/b] erstellt und zurückgegeben. Die GetEnumerator-Methode eines aufzählbaren Objekts gibt ein Enumeratorobjekt zurück, das den im Iteratorblock angegebenen Code kapselt. Wenn die MoveNext-Methode des Enumeratorobjekts aufgerufen wird, wird die Ausführung des Iteratorblockcodes ausgelöst. Aufzählbare Objekte weisen die folgenden Eigenschaften auf.
l Es implementiert die Schnittstellen IEnumerable und IEnumerable
l Es wird mit einer Kopie des Argumentwerts (falls vorhanden) initialisiert und übergibt den Instanzwert an den Funktionsmember.
Ein aufzählbares Objekt ist normalerweise eine Instanz einer vom Compiler generierten aufzählbaren Klasse, die den Code für einen Iteratorblock kapselt und die aufzählbare Schnittstelle implementiert, aber auch andere Implementierungen sind möglich. Wenn vom Compiler eine aufzählbare Klasse generiert wird, wird die Klasse in die Klasse eingebettet, die das Funktionsmitglied enthält, und verfügt über privaten Zugriff sowie einen Namen, der für die Verwendung durch den Compiler reserviert ist (§2.4.2).
Aufzählbare Objekte können mehr Schnittstellen implementieren als die hier dargestellten. Insbesondere kann ein aufzählbares Objekt auch die Schnittstellen IEnumerator und IEnumerator
22.3.1 GetEnumerator-Methode
Enumerable-Objekte stellen eine Implementierung der GetEnumerator-Methode der Schnittstellen IEnumerable und IEnumerable
Das Aufzählungsobjekt wird mit den tatsächlichen Parameterwerten initialisiert. Wenn das Aufzählungsobjekt initialisiert wird, wird sein Instanzwert gespeichert. Andererseits ist die Funktion des Aufzählungsobjekts wie in §22.2 beschrieben.
(Fortsetzung folgt)
Das Obige ist der Inhalt der C# 2.0-Spezifikation (Iterator) (1). Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website (www.php). .cn)!