Hier ist meine zuvor akzeptierte Antwort auf genau dieselbe Frage:
Rendite Keyword Mehrwert?
Eine andere Möglichkeit, Iteratormethoden zu betrachten, besteht darin, dass sie die harte Arbeit leisten, einen Algorithmus "von innen nach außen" zu drehen. Betrachten Sie einen Parser. Es zieht Text aus einem Stream, sucht darin nach Mustern und generiert eine logische Beschreibung des Inhalts auf hoher Ebene.
Jetzt kann ich es mir als Parserautor leicht machen, indem ich den SAX-Ansatz verwende, bei dem ich eine Rückrufschnittstelle habe, die ich benachrichtige, wenn ich das nächste Stück des Musters finde. Im Fall von SAX rufe ich jedes Mal, wenn ich den Anfang eines Elements finde, die beginElement
Methode auf und so weiter.
Dies schafft jedoch Probleme für meine Benutzer. Sie müssen die Handler-Schnittstelle implementieren und daher eine Zustandsmaschinenklasse schreiben, die auf die Rückrufmethoden reagiert. Dies ist schwer zu korrigieren, daher ist es am einfachsten, eine Standardimplementierung zu verwenden, die einen DOM-Baum erstellt, und dann haben sie die Möglichkeit, über den Baum zu gehen. Aber dann wird die gesamte Struktur im Speicher gepuffert - nicht gut.
Aber wie wäre es stattdessen, wenn ich meinen Parser als Iteratormethode schreibe?
IEnumerable<LanguageElement> Parse(Stream stream)
{
yield return new BeginStatement("if");
}
Das ist nicht schwieriger zu schreiben als der Callback-Interface-Ansatz - geben Sie einfach ein von meiner LanguageElement
Basisklasse abgeleitetes Objekt zurück, anstatt eine Callback-Methode aufzurufen.
Der Benutzer kann jetzt foreach verwenden, um die Ausgabe meines Parsers zu durchlaufen, sodass er eine sehr praktische, zwingende Programmierschnittstelle erhält.
Das Ergebnis ist, dass beide Seiten einer benutzerdefinierten API so aussehen, als hätten sie die Kontrolle und sind daher einfacher zu schreiben und zu verstehen.