Manchmal warnt Resharper vor:
Mögliche mehrfache Aufzählung von IEnumerable
Es gibt eine SO-Frage zum Umgang mit diesem Problem , und die ReSharper-Site erklärt hier auch die Dinge . Es enthält einen Beispielcode, der Sie dazu auffordert:
IEnumerable<string> names = GetNames().ToList();
Meine Frage bezieht sich auf diesen speziellen Vorschlag: Wird dies nicht immer noch dazu führen, dass die Sammlung in den 2 for-each-Schleifen zweimal aufgelistet wird?
c#
resharper
resharper-7.1
user2250250
quelle
quelle
Antworten:
GetNames()
gibt ein zurückIEnumerable
. Wenn Sie dieses Ergebnis speichern:Jedes Mal
foo
, wenn Sie aufzählen , wird dieGetNames()
Methode erneut aufgerufen (nicht wörtlich, ich kann keinen Link finden, der die Details richtig erklärt, aber sieheIEnumerable.GetEnumerator()
).Resharper sieht dies und schlägt vor, das Ergebnis der Aufzählung
GetNames()
in einer lokalen Variablen zu speichern , indem Sie es beispielsweise in einer Liste materialisieren:Dadurch wird sichergestellt, dass das
GetNames()
Ergebnis nur einmal aufgelistet wird, solange Sie sich darauf beziehenfooEnumerated
.Dies ist wichtig, da Sie normalerweise nur einmal auflisten möchten, z. B. wenn Sie
GetNames()
einen (langsamen) Datenbankaufruf ausführen.Da Sie die Ergebnisse in einer Liste materialisiert haben , spielt es keine Rolle mehr, dass Sie
fooEnumerated
zweimal aufzählen . Sie werden zweimal eine In-Memory-Liste durchlaufen.quelle
IEnumerable
wird für jede Aufzählung ausgewertet, nur diejenigen, die mit 'verzögerter Ausführung' implementiert sind (das ist der Link, den Sie vermisst haben, @CodeCaster). Die R # -Warnung kann ignoriert werden, wenn die zugrunde liegende Implementierung nicht verzögert ausgeführt wird, wie in diesem Fragenbeispiel, das aufruftToList()
, um sie in einer anderenIEnumerable
Variablen zu speichern .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/
quelle
GetNames()
wird nicht zweimal aufgerufen. Die Implementierung vonIEnumerable.GetEnumerator()
wird jedes Mal aufgerufen, wenn Sie die Sammlung mit auflisten möchtenforeach
. Wenn innerhalb derIEnumerable.GetEnumerator()
einige teure Berechnung gemacht wird, könnte dies ein Grund sein, darüber nachzudenken.quelle
Ja, Sie werden es ohne Zweifel zweimal aufzählen. Der Punkt ist jedoch, dass, wenn
GetNames()
eine verzögerte Linq-Abfrage zurückgegeben wird, deren Berechnung sehr teuer ist, diese zweimal ohne Aufruf vonToList()
oder berechnet wirdToArray()
.quelle