LINQ für IList optimieren

9

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.

In IEnumerator.MoveNext () :

  

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?

    
Steven Jeuris 02.05.2011, 21:08
quelle

2 Antworten

2

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:

%Vor%

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.

    
Gabe 03.05.2011, 05:38
quelle
0

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.

    
Charles Lambert 03.05.2011 04:58
quelle

Tags und Links