wake-up-neo.com

Resharper-Beispielcode zur Erläuterung von "Mögliche mehrfache Aufzählung von IEnumerable"

Manchmal warnt Resharper vor:

Mögliche mehrfache Aufzählung von IEnumerable

Es gibt eine SO Frage zur Behandlung dieses Problems , und die ReSharper-Site erklärt auch die Dinge hier Sie dies stattdessen zu tun:

IEnumerable<string> names = GetNames().ToList();

Meine Frage bezieht sich auf diesen speziellen Vorschlag: Führt dies nicht dazu, dass die Auflistung in den 2 for-each-Schleifen noch zweimal durchlaufen wird?

63
user2250250

GetNames() gibt ein IEnumerable zurück. Wenn Sie das Ergebnis speichern:

IEnumerable foo = GetNames();

Jedes Mal, wenn Sie foo aufzählen, wird die GetNames() -Methode erneut aufgerufen (nicht wörtlich, ich kann keinen Link finden, der die Details richtig erklärt, aber siehe IEnumerable.GetEnumerator() ).

Resharper erkennt dies und schlägt vor, dass Sie das Ergebnis der Aufzählung von GetNames() in einer lokalen Variablen speichern, indem Sie es beispielsweise in a materialisieren Liste:

IEnumerable fooEnumerated = GetNames().ToList();

Dadurch wird sichergestellt, dass das Ergebnis GetNames() nur einmal aufgelistet wird, solange Sie sich auf fooEnumerated beziehen.

Dies ist von Bedeutung, da Sie normalerweise nur eine einzige Aufzählung durchführen möchten, beispielsweise wenn GetNames() einen (langsamen) Datenbankaufruf ausführt.

Da Sie die Ergebnisse in einer Liste materialisiert haben , spielt es keine Rolle mehr, dass Sie fooEnumerated zweimal aufzählen. Sie werden zweimal über eine Liste im Speicher iterieren.

158
CodeCaster

Ich fand, dass dies der beste und einfachste Weg ist, mehrere Aufzählungen zu verstehen.

C # LINQ: Mögliche mehrfache Aufzählung von IEnumerable

https://helloacm.com/c-linq-possible-multiple-enumeration-of-ienumerable-resharper/

9
Ryan

GetNames() wird nicht zweimal aufgerufen. Die Implementierung von IEnumerable.GetEnumerator() wird jedes Mal aufgerufen, wenn Sie die Auflistung mit foreach aufzählen möchten. Wenn innerhalb der IEnumerable.GetEnumerator() eine teure Berechnung durchgeführt wird, kann dies ein Grund sein, dies zu berücksichtigen.

8
IronMan702

Ja, Sie werden es ohne Zweifel zweimal aufzählen. Aber der Punkt ist, wenn GetNames() eine träge linq-Abfrage zurückgibt, die sehr teuer zu berechnen ist, dann berechnet sie zweimal ohne einen Aufruf von ToList() oder ToArray().

4