2016-03-31 2 views
2

Resharper beschwert sich ständig darüber: Mögliche mehrfache Aufzählung von IEnumerable. Zum Beispiel:ELI5: Wie vermeidet die Konvertierung eines IEnumerable in eine Liste oder ein Array die Leistungseinbußen bei der mehrfachen Aufzählung von IEnumerable?

private int ParseLoanNumber(IEnumerable<string> lines) 
    { 
     var loanNumber = 0; 

     var item = lines.FirstOrDefault(l => l.StartsWith(" LN# 00")); 

     if (item != null) 
     { 
      loanNumber = item.ParseInt(8, 10).GetValueOrDefault(); 
     } 
     else 
     { 
      item = lines.FirstOrDefault(l => l.StartsWith(" LOAN-NO (CONT'D) 00")); 
      if (item != null) 
      { 
       loanNumber = item.ParseInt(19, 10).GetValueOrDefault(); 
      } 
     } 
     // Yada yada... 
    } 

Die empfohlene Lösung ist, die enumerable zu einem list oder array und iterieren, dass zu konvertieren.

Das verwirrt mich. Sie werden immer noch etwas aufzählen, und beide Typen (Arrays und Listen) implementieren IEnumerable. Also, wie löst das irgendetwas, oder verbessern Sie die Leistung in irgendeiner Weise?

Antwort

4

Weil du das schreiben:

public IEnumerable<int> GetNumbersSlowly() 
{ 
    for (var i = 0; i < 100; i++) 
    { 
     Thread.Sleep(10000); //Or retrieve from a website, etc 
     yield return i; 
    } 
} 

Wenn Sie es wie folgt verwenden:

var numbers = GetNumbersSlowly(); 
foreach(var number in numbers) { 
    //Do something 
} 
foreach(var number in numbers) { 
    //Do something 
} 

Es bedeutet, die (den Schlaf) geleistete Arbeit wird zweimal für jede Nummer getan. Wenn Sie das Enumerable einmal auswerten und es in einem Array oder einer Liste speichern, können Sie sicher sein, dass keine zusätzlichen Schritte zur Rückgabe der Elemente ausgeführt werden.

Da Sie eine IEnumerable<string> nehmen, wissen Sie wirklich nicht, dass der Anrufer nicht das oben genannte getan hat.

Wenn Sie denken, mein Beispiel selten sein könnte oder eine Kante Fall, es gilt auch für Dinge wie diese:

var someSource = new List<int> { 1, 2, 3, 4, 5 }; 
var numbers = someSource.Select(s => s * 100000); 

Nun jedes Mal, wenn Sie iterieren numbers, bist du auch die Berechnung wieder zu tun. In diesem Fall ist es nicht viel Arbeit, warum es mehr als Sie brauchen (und es ist nicht ungewöhnlich, dass es nicht-triviale Arbeit ist).

+2

Nur um andere Beispiele zu geben; einige 'IEnumerable ' sind einfach nicht wiederholbar - zum Beispiel können sie Daten aus einem 'Socket' oder einer externen Quelle zeichnen, wie eine Datenbankabfrage, die einen' IDataReader' umhüllt ("dapper" erlaubt beispielsweise diese Art der Verwendung), oder sie könnten Zahlen aus einem PRNG ziehen usw. –

+0

Also, wenn ich das richtig verstehe, kommt die Leistungseinbuße aus der Nichtumwandlung von * verzögerter Ausführung *. Ist das ungefähr richtig? –

Verwandte Themen