Frage

ich weiß was yield tut es, und ich habe ein paar Beispiele gesehen, aber mir fallen keine realen Anwendungen ein. Haben Sie es verwendet, um ein bestimmtes Problem zu lösen?

(Idealerweise ein Problem, das nicht anders gelöst werden kann)

War es hilfreich?

Lösung

Mir ist klar, dass dies eine alte Frage ist (vor Jon Skeet?), aber ich habe selbst in letzter Zeit über diese Frage nachgedacht.Leider erwähnen die aktuellen Antworten hier (meiner Meinung nach) nicht den offensichtlichsten Vorteil der Ertragsaussage.

Der größte Vorteil der yield-Anweisung besteht darin, dass Sie damit über sehr große Listen iterieren können, wobei der Speicher viel effizienter genutzt wird als beispielsweise mit einer Standardliste.

Angenommen, Sie haben eine Datenbankabfrage, die 1 Million Zeilen zurückgibt.Sie könnten alle Zeilen mit einem DataReader abrufen und in einer Liste speichern, wofür list_size * row_size Bytes Speicher erforderlich wären.

Oder Sie könnten die yield-Anweisung verwenden, um einen Iterator zu erstellen und jeweils nur eine Zeile im Speicher zu speichern.Dies gibt Ihnen tatsächlich die Möglichkeit, eine „Streaming“-Funktion für große Datenmengen bereitzustellen.

Darüber hinaus verwenden Sie im Code, der den Iterator verwendet, eine einfache foreach-Schleife und können bei Bedarf entscheiden, aus der Schleife auszubrechen.Wenn Sie den Vorgang vorzeitig unterbrechen, haben Sie nicht den Abruf des gesamten Datensatzes erzwungen, wenn Sie beispielsweise nur die ersten fünf Zeilen benötigten.

Hinsichtlich:

Ideally some problem that cannot be solved some other way

Die yield-Anweisung bietet Ihnen nichts, was Sie mit Ihrer eigenen benutzerdefinierten Iterator-Implementierung nicht tun könnten, aber sie erspart Ihnen das Schreiben des oft erforderlichen komplexen Codes.Es gibt nur sehr wenige Probleme (wenn überhaupt), die nicht auf mehrere Arten gelöst werden können.

Hier sind ein paar aktuellere Fragen und Antworten, die detailliertere Informationen liefern:

Mehrwert des Yield-Keywords?

Ist yield außerhalb von LINQ nützlich?

Andere Tipps

Tatsächlich verwende ich es auf einer nicht traditionellen Art und Weise auf meiner Website IdeaPipe

public override IEnumerator<T> GetEnumerator()
{
    // goes through the collection and only returns the ones that are visible for the current user
    // this is done at this level instead of the display level so that ideas do not bleed through
    // on services
    foreach (T idea in InternalCollection)
        if (idea.IsViewingAuthorized)
            yield return idea;
}

Im Grunde wird also geprüft, ob das Anzeigen der Idee derzeit autorisiert ist, und wenn ja, wird die Idee zurückgegeben.Ist dies nicht der Fall, wird es einfach übersprungen.Dadurch kann ich die Ideen zwischenspeichern und sie dennoch den berechtigten Benutzern anzeigen.Andernfalls müsste ich sie jedes Mal auf der Grundlage der Berechtigungen neu abrufen, während sie nur alle 1 Stunde neu eingestuft werden.

Eine interessante Verwendung ist als Mechanismus für die asynchrone Programmierung, insbesondere für Aufgaben, die mehrere Schritte umfassen und in jedem Schritt denselben Datensatz erfordern.Zwei Beispiele hierfür wären Jeffery Richters AysncEnumerator Teil 1 Und Teil 2.Auch die Concurrency and Coordination Runtime (CCR) nutzt diese Technik CCR-Iteratoren.

Die Operatoren von LINQ für die Enumerable-Klasse werden als Iteratoren implementiert, die mit der yield-Anweisung erstellt werden.Es ermöglicht Ihnen, Operationen wie Select() und Where() zu verketten, ohne tatsächlich etwas aufzuzählen, bis Sie den Enumerator tatsächlich in einer Schleife verwenden, normalerweise durch Verwendung von für jede Stellungnahme.Da außerdem nur ein Wert berechnet wird, wenn Sie IEnumerator.MoveNext() aufrufen und Sie entscheiden, die Sammlung mittendrin zu stoppen, ersparen Sie sich den Leistungseinbruch, der durch die Berechnung aller Ergebnisse entsteht.

Iteratoren können auch verwendet werden, um andere Arten der verzögerten Auswertung zu implementieren, bei der Ausdrücke nur dann ausgewertet werden, wenn Sie sie benötigen.Sie können auch verwenden Ertrag für ausgefallenere Dinge wie Coroutinen.

Eine weitere gute Verwendung von yield besteht darin, eine Funktion für die Elemente eines IEnumerable auszuführen und ein Ergebnis eines anderen Typs zurückzugeben, zum Beispiel:

public delegate T SomeDelegate(K obj);

public IEnumerable<T> DoActionOnList(IEnumerable<K> list, SomeDelegate action)
{
    foreach (var i in list)
        yield return action(i);
}

Durch die Verwendung von Yield kann ein Downcasting auf einen konkreten Typ verhindert werden.Dies ist praktisch, um sicherzustellen, dass der Konsument der Sammlung sie nicht manipuliert.

Sie können auch verwenden yield return um eine Reihe von Funktionsergebnissen als Liste zu behandeln.Stellen Sie sich zum Beispiel ein Unternehmen vor, das seine Mitarbeiter alle zwei Wochen bezahlt.Mit diesem Code könnte man eine Teilmenge der Gehaltsabrechnungsdaten als Liste abrufen:

void Main()
{
    var StartDate = DateTime.Parse("01/01/2013");
    var EndDate = DateTime.Parse("06/30/2013");
    foreach (var d in GetPayrollDates(StartDate, EndDate)) {
        Console.WriteLine(d);
    }
}

// Calculate payroll dates in the given range.
// Assumes the first date given is a payroll date.
IEnumerable<DateTime> GetPayrollDates(DateTime startDate, DateTime endDate, int     daysInPeriod = 14) {
    var thisDate = startDate;
    while (thisDate < endDate) {
        yield return thisDate;
        thisDate = thisDate.AddDays(daysInPeriod);
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top