2010-05-14 15 views

Antwort

6

Das yield Konstrukt verwendet wird, einen Iterator zu erstellen, die mehrere Werte hintereinander produzieren können:

IEnumerable<int> three_numbers() { 
    yield return 1; 
    yield return 2; 
    yield return 3; 
} 
... 
foreach (var i in three_numbers()) { 
    // i becomes 1, 2 and 3, in turn. 
} 
7

Ausbeute ist für Iteratoren.

Es lässt Sie eine Liste in kleinen Schwalben verarbeiten, die für große Listen nett ist.

Das magische an Yield ist, dass es sich daran erinnert, wo Sie zwischen den Aufrufen stehen.

Wenn Sie nicht iterieren, brauchen Sie keine Rendite.

21

Verwenden Sie die Ausbeute, wenn Sie ein Enumerable zurückgeben, und Sie haben nicht alle Ergebnisse zu diesem Zeitpunkt.

Praktisch habe ich Ausbeute verwendet, wenn ich durch einen großen Informationsblock (Datenbank, flache Datei usw.) iterieren möchte, und ich möchte nicht zuerst alles im Speicher laden. Yield ist eine gute Möglichkeit, um den Block zu durchlaufen, ohne alles auf einmal zu laden.

1

Ertragsrückgabe wird die Methode von diesem Punkt fortgesetzt. Sie möchten beispielsweise ein Array oder eine Liste durchlaufen und jedes Element zu dem Zeitpunkt zurückgeben, an dem der Aufrufer verarbeitet werden soll. Sie werden also die Rendite verwenden. Wenn Sie alles zurückkehren wollen und dann getan, brauchen Sie nicht zu tun, dass

1

Es erklärt hier :

C# Language Reference
yield (C# Reference)

Das Verfahren wird jeden einzelnen Wert zurückgeben, so genannt, dass sie durch den Anrufer aufgezählt werden können.

Das bedeutet, dass Sie yield verwenden müssen, wenn Sie jedes mögliche Ergebnis von einer Iteration zurückgegeben möchten.

6

Das Schlüsselwort yield ist unglaublich mächtig. Im Grunde können Sie Objekte IEnumerable und IEnumerator schnell zurückgeben, ohne sie explizit zu codieren.

Betrachten Sie ein Szenario, in dem Sie die Schnittmenge zweier IEnumerable-Objekte zurückgeben möchten. So würden Sie es mit dem Schlüsselwort yield machen.

public static class Program 
{ 
    public static void Main() 
    { 
    IEnumerable<object> lhs = new List<int> { 1, 2, 3, 4, 5 }; 
    IEnumerable<object> rhs = new List<int> { 3, 4, 5, 6, 7 }; 
    foreach (object item in IntersectExample.Intersect(lhs, rhs)) 
    { 
     Console.WriteLine(item); 
     break; 
    } 
    } 
} 

public static class IntersectExample 
{ 
    public static IEnumerable<object> Intersect(IEnumerable<object> lhs, IEnumerable<object> rhs) 
    { 
    var hashset = new HashSet<object>(); 
    foreach (object item in lhs) 
    { 
     if (!hashset.Contains(item)) 
     { 
     hashset.Add(item); 
     } 
    } 
    foreach (object item in rhs) 
    { 
     if (hashset.Contains(item)) 
     { 
     yield return item; 
     } 
    } 
    } 
} 

Es ist schwer zu verstehen, bis Sie vollständig wissen, was vor sich geht. Wenn Sie zwei Sätze schneiden, schließen Sie normalerweise den gesamten Vorgang ab, bevor Sie das Ergebnis an den Aufrufer zurückgeben. Das bedeutet, dass die Laufzeitkomplexität der Operation O(m + n) ist, wobei m und n die Größen der Sammlungen sind, die durchschnitten werden, unabhängig davon, was Sie danach mit dem Ergebnis tun. Aber in meinem Beispiel wollte ich nur den ersten Gegenstand aus dem Ergebnis abholen. Die Verwendung eines IEnumerable, das mit dem Schlüsselwort yield erstellt wurde, macht es sehr einfach, einen Teil der Verarbeitung zu verzögern, bis es tatsächlich benötigt wird. Mein Beispiel läuft in O(m). Die Alternative besteht darin, die IEnumerable zu codieren und den Zustand manuell darin zu behalten. Das Schlüsselwort yield ist, dass es diese Zustandsmaschine für Sie erstellt.

Verwandte Themen