2010-05-14 6 views
8

Ich finde mich oft mit einer Situation, wo ich eine Operation auf einer Reihe von Eigenschaften durchführen muss. Die Operation kann alles Mögliche sein, indem überprüft wird, ob eine bestimmte Eigenschaft mit irgendetwas in der Menge zu einer einzelnen Iteration von Aktionen übereinstimmt. Manchmal wird die Menge beim Aufruf der Funktion dynamisch erzeugt, manche werden mit einer einfachen LINQ-Anweisung erstellt, manchmal ist es eine fest codierte Menge, die immer gleich bleibt. Es existiert aber immer eine Konstante: das Set existiert nur für einen einzigen Vorgang und hat davor oder danach keine Verwendung.Welcher C# -Container ist für nur eine Operation am ressourceneffizientesten?

Mein Problem ist, ich habe so viele Punkte in meiner Anwendung, wo dies notwendig ist, aber ich sehe sehr, sehr inkonsequent in, wie ich diese Sätze speichern. Einige von ihnen sind Arrays, einige sind Listen, und gerade habe ich ein paar verknüpfte Listen gefunden. Keine der Operationen, um die es mir besonders geht, muss sich um Indizes, Containergröße, Reihenfolge oder andere Funktionen kümmern, die von einem der einzelnen Containertypen vergeben werden. Ich habe die Ressourceneffizienz ausgewählt, weil es eine bessere Idee ist, als Münzen zu werfen. Ich denke, da die Array-Größe konfiguriert ist und es ein sehr elementarer Container ist, könnte das meine beste Wahl sein, aber ich denke, es ist eine bessere Idee, herum zu fragen. Alternativ, wenn es eine bessere Wahl gibt, nicht aus Ressourceneffizienz, sondern strikt als eine bessere Wahl für diese Art von Situation, wäre das auch schön.

+5

Ich denke, Sie sollten sich nicht zu viel Gedanken über die Ressourceneffizienz machen, es sei denn, das Profil zeigt, dass ein Problem vorliegt. Aus der Perspektive, ob es einen »einzig wahren« Umgang gibt, ist dies jedoch noch immer eine berechtigte Frage. – Joey

+0

Ich bin nicht besonders besorgt über Ressourceneffizienz, ich wählte es als die Metrik, da ich wirklich einen Grund brauche, jenseits der zufälligen Wahl. Ich könnte die Frage auf "Die beste Wahl im Allgemeinen" umstrukturieren. –

+0

Als pedantischer Programmierer verstehe ich Ihre Bedenken völlig, obwohl es, wie Rössel sagte, wahrscheinlich nicht so wichtig ist. Ich habe es nie profiliert, da mir das Performanceproblem nie aufgefallen ist, aber ich persönlich benutze ein Array für statischen Inhalt und eine Liste, wenn ich aus etwas anderem eine Liste zusammenstellen muss. – Coincoin

Antwort

6

Mit Ihrer Bestätigung, dass es mehr um Codierungskonsistenz als um Leistung oder Effizienz geht, denke ich, dass die allgemeine Praxis eine List<T> ist. Der tatsächliche Sicherungsspeicher ist ein Array, sodass Sie nicht wirklich viel (wenn überhaupt etwas Bemerkenswertes) an Container-Overhead verlieren. Ohne weitere Qualifikationen bin ich mir nicht sicher, ob ich mehr bieten kann.

Natürlich, wenn Sie sich wirklich nicht für die Dinge interessieren, die Sie in Ihrer Frage auflisten, geben Sie einfach Ihre Variablen IEnumerable<T> ein und Sie haben nur mit dem eigentlichen Container zu tun, wenn Sie ihn füllen; Wo Sie konsumieren, wird es völlig konsistent sein.

+0

Ich würde für einfache Arrays argumentieren, aber ich stimme überein IEnumerable für Schnittstellen zu verwenden, damit wir beide richtig sein können. –

+1

@Steven: Ich wählte 'List ' einfach weil a) es Arrays auf dem Backend verwendet, so dass Sie wirklich nichts verlieren, und b) es Ihnen erlaubt, mit Sets konsistent zu sein, die sowohl mit bekannten als auch unbekannten Größen beginnen . Eine Liste bietet auch Flexibilität, wenn Sie sie zu einem späteren Zeitpunkt bereitstellen müssen, da sie einfach über die AsReadOnly-Funktion read-only ausgeführt werden kann, während ein Array einen vollständig neuen Typ benötigt, um schreibgeschützt zu sein. –

+0

Gute Gründe. Als C++ - Flüchtling finde ich List als einen geeigneten Ersatz für Vektor. –

2

Es gibt zwei Grundprinzipien, die bei der Ressourceneffizienz beachtet werden müssen.

  • Runtime Komplexität
  • Speicher-Overhead

Sie sagten, Indizes und Ordnung keine Rolle spielen und dass ein häufiger Vorgang entspricht. Eine Dictionary<T> (die eine hashtable ist) ist ein idealer Kandidat für diese Art von Arbeit. Nachschlagevorgänge auf den Tasten sind sehr schnell, was beim Abgleich hilfreich wäre. Der Nachteil ist, dass es etwas mehr Speicher verbraucht, als unbedingt erforderlich wäre. Der übliche Lastfaktor liegt bei 0,8, also sprechen wir nicht von einem großen Anstieg oder so.

Für Ihre anderen Operationen können Sie feststellen, dass ein Array oder List<T> eine bessere Option ist, vor allem, wenn Sie nicht die schnellen Lookups benötigen. Solange Sie keine speziellen Funktionen (Suchen, Sortieren usw.) benötigen, ist es schwierig, die allgemeinen Ressourceneigenschaften von Array-basierten Containern zu übertreffen.

+0

Die Verwendung eines 'HashSet' wäre besser, imo, da er keinen zugeordneten Wert mit den Schlüsseln benötigt. – tzaman

+0

Wenn Suchen und/oder Prüfen, ob ein Objekt in der Sammlung vorhanden ist, viel häufiger als das Ändern der Liste wären, dann wären 'Dictionary' und' Hashset' gute Kandidaten, aber nur für eine allgemeine "Tasche", führen sie ein eine kleine Menge an Komplexität, die verschwendet wurde. –

+0

@tzaman: Guter Punkt. –

0

Liste ist wahrscheinlich in Ordnung im Allgemeinen. Es ist leicht zu verstehen (im programmierten Sinne) und einigermaßen effizient. Die codierten Sammlungen (z. B. Dict, SortedList) lösen eine Ausnahme aus, wenn Sie einen Eintrag mit einem doppelten Schlüssel hinzufügen. Dies ist jedoch möglicherweise kein Problem für das, woran Sie gerade arbeiten.

Nur wenn Sie feststellen, dass Sie in eine CPU-Zeit oder Speichergröße Problem auftreten sollten Sie die Verbesserung der "Effizienz", und dann erst nach der Feststellung, dass dieser ist der Flaschenhals.

Egal, welchen Ansatz Sie verwenden, es wird immer noch die zugrunde liegenden Objekte (Sammlung oder Iterator) erstellen und löschen, die schließlich Müll gesammelt werden, wenn die Anwendung lang genug läuft.

Verwandte Themen