Ihre Frage ist eine der Schleifen-Invarianten-Analyse - kann der Compiler einen Ausdruck in einer Schleife erkennen, die nicht vom Zustand der Schleife abhängt und keine Nebenwirkungen hat?
Es gibt gute Gründe zu hoffen, dass der Compiler beide Aussagen erfüllen könnte - der Compiler könnte schlau genug sein zu wissen, dass sich der Aufruf von ToString()
in einer Enumeration nicht ändert; und das Aufrufen von ToString()
in einer Aufzählung hat keine nennenswerten Nebenwirkungen.
Es könnte Gründe geben, warum der Compiler aktiv entscheiden würde, die Invariante nicht zu hissen - vielleicht ist das Aufrufen der Funktion etwas schneller als das Speichern einer zusätzlichen Variable auf dem Stack.
Die Frage läuft darauf hinaus, ob es tut .
Ich habe das folgende Programm mit VS2012 Targeting .NET 4.6 kompiliert und mit optimierten Optimierungen kompiliert. Es scheint, dass der Compiler nicht ausgewählt hat, die Invariante aus der Schleife zu heben:
%Vor% Hier ist die rohe IL aus dem Programm, das ich mit ILSpy 2.3.1 erhalten habe. Beachten Sie den Aufruf von ToString()
, genau in der Mitte der Schleife.
Ich bin auch neugierig geworden, ob der Laufzeit-JITer die Invariante hissen würde, aber es scheint auch nicht so zu sein. Ich habe den Code folgendermaßen geändert, um die Baugruppe sauberer zu machen:
%Vor%Und dann VS-Debugger verwendet, um die Assembly zu erhalten, wobei darauf zu achten ist, dass VS den JITer optimieren ließ. Der Aufruf von ToString () wurde noch nicht ausgelöst:
%Vor%Nein, aber Sie können die Komplexität erheblich reduzieren, indem Sie so etwas tun:
%Vor%Die Suche nach Wörterbuchwerten hat eine Komplexität von O (1).
Ich denke, eine Alternative ist HashSet , wie Sie es getan haben nur Schlüssel. Eine interessante Frage und Antworten zum Aufbau einer HashSet
aus einer Liste finden Sie hier .
[Bearbeiten] Nach Scotts Kommentar werde ich eine Option mit Hashset (auch in O (1)) einfügen:
%Vor% Basierend auf der korrekten Beobachtung von btlog
wird der Beispielcode für Duplikate fehlschlagen. Es kann umgangen werden entweder:
Distinct
verwendest
Der zweite Ansatz erhöht jedoch die Komplexität auf O (N)
Tags und Links c# performance