Читать книгу Dojos für Entwickler - Stefan Lieser - Страница 12
Einer nach dem anderen
ОглавлениеEin Detail ist bei der Realisierung von Flows ganz wichtig: Weitergereicht werden sollten nach Möglichkeit jeweils Daten vom Typ IEnumerable<T>. Dadurch besteht nämlich die Möglichkeit, auf diesen Daten mit LINQ zu operieren. Ferner können die einzelnen Flowstages dann beliebig große Datenmengen verarbeiten, da bei Verwendung von IEnumerable<T> nicht alle Daten vollständig im Speicher existieren müssen, sondern Element für Element bereitgestellt werden können. Im Idealfall fließt also zwischen den einzelnen Flowstages immer nur ein einzelnes Element. Es wird nicht etwa das gesamte Ergebnis der ersten Stage berechnet und dann vollständig weitergeleitet.
Im Beispiel von Listing 2 führt die Verwendung von yield return dazu, dass der Compiler einen Enumerator erzeugt. Dieser Enumerator liefert nicht sofort die gesamte Aufzählung, sondern stellt auf Anfrage Wert für Wert bereit. Bei Ausführung der Methode Flow() werden also zunächst nur die einzelnen Aufzählungen und Funktionen miteinander verbunden. Erst wenn das erste Element aus dem Ergebnis entnommen werden soll, beginnen die Enumerato-ren, Werte zu liefern. Der Flow kommt also erst dann in Gang, wenn jemand hinten das erste Element „herauszieht“.
Listing 2: Rückgabedaten vom Typ IEnumerable nutzen.
public void Flow() {
var input = Input();
var x1 = A(input);
var x2 = B(x1);
var result = C(x2);
foreach(var value in result) {
...
}
}
public IEnumerable<string> Input() {
yield return "Äpfel";
yield return "Birnen";
yield return "Pflaumen";
}
public IEnumerable<string> A(IEnumerable<string> input) {
foreach (var value in input) {
yield return string.Format("({0})", value);
}
}
public IEnumerable<string> B(IEnumerable<string> input) {
foreach (var value in input) {
yield return string.Format("[{0}]", value);
}
}
public IEnumerable<string> C(IEnumerable<string> input) {
foreach (var value in input) {
yield return string.Format("-{0}-", value);
}
}
Als erste ist die Funktion C an der Reihe. Sie entnimmt aus der ihr übergebenen Aufzählung x2 das erste Element. Dadurch kommt B ins Spiel und entnimmt ihrerseits der Aufzählung x1 den ersten Wert. Dies setzt sich fort, bis die Methode Input den ersten Wert liefern muss. Im Flow werden die einzelnen Werte sozusagen von hinten durch den Flow gezogen. Ein Flow bietet in Verbindung mit IEnumerable<T> und yield return die Möglichkeit, unendlich große Datenmengen zu verarbeiten, ohne dass eine einzelne Flowstage die Daten komplett im Speicher halten muss.