Vor einiger Zeit habe ich eine IList
-Erweiterungsmethode geschrieben, um einen Teil einer Liste mithilfe der Indizes aufzuzählen. Beim Refactoring wurde mir klar, dass eine ähnliche Abfrage durch Aufruf von Skip(toSkip).Take(amount)
durchgeführt werden könnte. Beim Benchmarking habe ich festgestellt, dass Skip
nicht für IList
optimiert ist. Mit ein bisschen Googeln endete ich bei einem Jon Skeet Post, diskutieren, warum die Optimierung von Methoden wie Skip
gefährlich ist .
Soweit ich den Artikel verstehe, ist das Problem, dass keine Ausnahme in den optimierten Methoden geworfen wird, wenn die Sammlung geändert wird, sondern als Kommentar die MSDN-Dokumentation Konflikte selbst.
Wenn Änderungen an der Sammlung vorgenommen werden, wie Hinzufügen, Ändern oder Löschen Elemente, der Enumerator ist unwiderruflich für ungültig erklärt und der nächste Rufen Sie MoveNext oder Reset auf InvalidOperationException.
In IEnumerator.GetEnumerator () :
Wenn Änderungen an der Sammlung vorgenommen werden, wie Hinzufügen, Ändern oder Löschen Elemente, der Enumerator ist unwiderruflich für ungültig erklärt und sein Verhalten ist nicht definiert .
Ich sehe Verdienste in beiden Konventionen, und bin ein bisschen verloren, ob oder nicht zu optimieren. Was ist eine richtige Lösung? Ich habe einen IList.AssumeImmutable()
-Ansatz in Anlehnung an AsParallel()
erwogen, wie Kris Vandermotten in den Kommentaren erwähnt hat. Gibt es bereits eine Implementierung oder ist es eine schlechte Idee?
Ich stimme Rafe zu, dass das undefinierte Verhalten korrekter ist. Nur versionierte Sammlungen können Ausnahmen auslösen und nicht alle Sammlungen werden versioniert (Arrays sind das größte Beispiel). Selbst versionierte Sammlungen können sich möglicherweise nicht korrekt verhalten, wenn Sie zwischen den Aufrufen von MoveNext
genau 2 ^ 32 Änderungen vornehmen.
Angenommen, Sie interessieren sich wirklich für das Versionsverhalten, besteht die Lösung darin, für jede% Iteration Enumerator
für IList
zu erhalten und MoveNext
aufzurufen:
Auf diese Weise erhalten Sie das O (1) -Verhalten durch Indizierung, aber Sie erhalten immer noch das Verhalten zum Auslösen der Ausnahme, indem Sie MoveNext
aufrufen. Beachten Sie, dass wir für die Ausnahme-Nebenwirkungen nur MoveNext
aufrufen. wir ignorieren die Werte, für die es aufzählt.
Die ReadOnlyCollection -Klasse kann bei Ihrer unveränderlichen Sammlung hilfreich sein.
Mein Tipp: Ich persönlich würde nicht versuchen, den Compiler "auszutricksen", außer Sie haben ein Performance-Problem. Sie wissen nie, die nächste Version könnte Ihren optimierten Code doppelt so langsam wie das Original laufen lassen. Nicht präventiv optimieren. Die im Framework bereitgestellten Methoden können einen wirklich optimierten Code erzeugen, der nur schwer zu implementieren wäre.
hier ist ein Artikel von msdn, der Informationen darüber gibt, welche Sammlungen für verschiedene Zwecke verwendet werden sollen . Ich würde eine geeignete Sammlung für die Aufgabe verwenden, anstatt zu versuchen, Skip and Take zu optimieren.
Tags und Links optimization .net c# linq skip