it-swarm.com.de

Gibt es jemals einen Grund, ein Array zu verwenden, wenn Listen verfügbar sind?

Wie es scheint List<T> in C # kann alles, was ein Array kann, und mehr und scheint auch in Bezug auf Speicher und Leistung genauso effizient zu sein wie ein Array.

Warum sollte ich jemals ein Array verwenden wollen?

Ich frage offensichtlich nicht nach Fällen, in denen eine API oder eine andere externe Einschränkung (d. H. Die Hauptfunktion) die Verwendung eines Arrays erfordert ... Ich frage nur nach dem Erstellen neuer Datenstrukturen in meinem eigenen Code.

30
JoelFan

Aus dem gleichen Grund fahre ich keinen LKW, wenn ich zur Arbeit gehe. Ich verwende nichts, dessen Funktionen ich nicht nutzen werde.

Zuallererst ist ein Array ein primitives Konstrukt, daher ist ein Array sicher schneller und effizienter als eine Liste <>, sodass Ihr Argument nicht wahr ist. Array ist auch überall verfügbar und Entwicklern bekannt, die verschiedene Sprachen und Plattformen verwenden.

Der wichtigste Grund, warum ich ein Array anstelle einer Liste <> verwende, ist, dass die Daten feste Länge sind. Wenn ich keine Elemente zu dieser Datenerfassung hinzufügen oder daraus entfernen möchte, möchte ich sicherstellen, dass der Typ dies widerspiegelt.

Nehmen wir an, Sie implementieren eine neue Datenstruktur und haben einige Artikel darüber gelesen. Während Sie bestimmte Algorithmen implementieren, können Sie sich nicht immer darauf verlassen, dass jemand anderes einen Typ implementiert, der für allgemeine Zwecke bestimmt ist. Es ändert sich von .NET zu Mono und sogar zwischen verschiedenen Versionen des Frameworks.

Und manchmal ist es einfacher, einen Code zu portieren, der ein Array anstelle eines Framework-abhängigen Typs verwendet.

27
Mert Akcakaya

Sie benötigen natürlich Arrays, um Ihre Sammlung von veränderlichen Strukturen zu verwalten, und was würden wir ohne diese tun.

struct EvilMutableStruct { public double X; } // don't do this

EvilMutableStruct[] myArray = new EvilMutableStruct[1];
myArray[0] = new EvilMutableStruct()
myArray[0].X = 1; // works, this modifies the original struct

List<EvilMutableStruct> myList = new List<EvilMutableStruct>();
myList.Add(new EvilMutableStruct());
myList[0].X = 1; // does not work, the List will return a *copy* of the struct

(Beachten Sie, dass es einige Fälle geben kann, in denen ein Array veränderlicher Strukturen wünschenswert ist, aber normalerweise ist dieses unterschiedliche Verhalten veränderlicher Strukturen in Arrays im Vergleich zu anderen Sammlungen eine Fehlerquelle, die vermieden werden sollte.)


Im Ernst, Sie benötigen ein Array, wenn Sie ein Element als Referenz übergeben. d.h.

Interlocked.Increment(ref myArray[i]);  // works
Interlocked.Increment(ref myList[i]);   // does not work, you can't pass a property by reference

Dies kann für sperrenfreien threadsicheren Code hilfreich sein.


Sie benötigen ein Array, wenn Sie initialisieren Ihre Sammlung mit fester Größe mit dem Standardwert.

double[] myArray = new double[1000]; // contains 1000 '0' values
                                     // without further initialisation

List<double> myList = new List<double>(1000) // internally contains 1000 '0' values, 
                                             // since List uses an array as backing storage, 
                                             // but you cannot access those
for (int i =0; i<1000; i++) myList.Add(0);   // slow and inelegant

(Beachten Sie, dass es möglich wäre, einen Konstruktor für List zu implementieren, der dasselbe tut. Es ist nur so, dass c # diese Funktion nicht bietet.)


sie benötigen ein Array, wenn Sie effizient kopieren Teile der Sammlung möchten

Array.Copy(array1, index1, array2, index2, length) // can't get any faster than this

double[,] array2d = new double[10,100];
double[] arraySerialized = new double[10*100];
Array.Copy(array2d, 0, arraySerialized, 0, arraySerialized.Length);
// even works for different dimensions

(Auch dies könnte auch für List implementiert werden, aber diese Funktion ist in c # nicht vorhanden.)

19
HugoRune

Warum sollte ich jemals ein Array verwenden wollen?

Selten, Sie haben ein Szenario, in dem Sie wissen, dass Sie eine feste Anzahl von Elementen benötigen. Aus gestalterischer Sicht sollte dies vermieden werden. Wenn Sie drei Dinge benötigen, bedeutet die Art des Geschäfts, dass Sie in der nächsten Version sehr oft vier benötigen.

Wenn dieses seltene Szenario tatsächlich auftritt, ist es dennoch nützlich, ein Array zu verwenden, um diese Invariante mit fester Größe zu erzwingen. Es gibt anderen Programmierern ein Signal, dass es sich um eine feste Größe handelt, und hilft, Missbrauch zu verhindern, wenn jemand ein Element hinzufügt oder entfernt, wodurch die Erwartungen an anderer Stelle im Code gebrochen werden.

15
Telastyn

Ihre Frage wurde tatsächlich bereits zuvor beantwortet .

und scheint auch in Bezug auf Speicher und Leistung genauso effizient zu sein wie ein Array.

Ist es nicht. Aus der Frage, die ich verlinkt habe:

List/foreach:  3054ms (589725196)
Array/foreach: 1860ms (589725196)

Arrays sind in bestimmten wichtigen Fällen doppelt so schnell. Ich bin sicher, dass sich die Speichernutzung auch nicht trivial unterscheidet.

Da die Hauptprämisse Ihrer Frage somit besiegt ist, gehe ich davon aus, dass dies Ihre Frage beantwortet. Darüber hinaus werden Ihnen manchmal Arrays von der Win32-API, dem Shader Ihrer GPU oder einer anderen Nicht-DotNet-Bibliothek aufgezwungen.

Selbst innerhalb von DotNet verbrauchen einige Methoden Arrays und/oder geben sie zurück (z. B. String.Split). Dies bedeutet, dass Sie entweder die Kosten für das ständige Aufrufen von ToList und ToArray auffressen müssen oder das Array anpassen und verwenden müssen, um möglicherweise den Zyklus fortzusetzen, indem Sie dies an arme nachgeschaltete Benutzer von - weitergeben. dein Code.

Weitere Fragen und Antworten zum Stapelüberlauf zu diesem Thema:

10
Superbest

Dies gilt auch für andere Sprachen mit Listen (z. B. Java oder Visual Basic). In einigen Fällen müssen Sie ein Array verwenden, da eine Methode ein Array anstelle einer Liste zurückgibt.

In einem tatsächlichen Programm wird ein Array meiner Meinung nach nicht sehr oft verwendet, aber manchmal wissen Sie, dass die Daten eine feste Größe haben, und Sie mögen den geringen Leistungsgewinn, den Sie durch die Verwendung eines Arrays erzielen. Mikrooptimierung wäre ein gültiger Grund, ebenso wie eine Methode, die eine Liste zurückgibt, oder die Notwendigkeit einer mehrdimensionalen Datenstruktur.

3
Dylan Meeus

Zusätzlich zu den in anderen Antworten aufgeführten Gründen benötigt das Array-Literal weniger Zeichen, um Folgendes zu deklarieren:

var array = new [] { "A", "B", "C" };
var list = new List<string>() { "A", "B", "C" };

Die Verwendung eines Arrays anstelle von List macht den Code etwas kürzer und nur ein bisschen lesbarer, wenn (1) Sie ein IEnumerable<T> - Literal übergeben müssen oder (2) wenn andere Funktionen von List spielt keine Rolle und Sie müssen ein listähnliches Literal verwenden.

Ich habe dies gelegentlich in Unit-Tests gemacht.

3
ikh

Dies ist ausschließlich aus der Perspektive von OO).

Ich kann mir zwar keinen Grund vorstellen, nur ein Array weiterzugeben, aber ich kann durchaus Situationen erkennen, in denen eine klasseninterne Array-Darstellung wahrscheinlich die beste Wahl ist.

Während es andere Optionen gibt, die ähnliche Eigenschaften aufweisen, scheint keine so intuitiv zu sein wie ein Array für Probleme mit Verarbeitungspermutationen, die für Schleifen, Matrixdarstellungen, Bitmaps und Datenverschachtelungsalgorithmen verschachtelt sind.

Es gibt eine beträchtliche Anzahl wissenschaftlicher Bereiche, die sich weitgehend auf Matrixmathematik stützen. (z. B. Bildverarbeitung, Datenfehlerkorrektur, digitale Signalverarbeitung, eine Vielzahl angewandter mathematischer Probleme). Die meisten Algorithmen in diesen Feldern sind in Bezug auf die Verwendung mehrdimensionaler Arrays/Matrizen geschrieben. Es wäre daher natürlicher, die Algorithmen so zu implementieren, wie sie definiert sind, als sie "softwarefreundlicher" zu machen, auf Kosten des Verlusts der direkten Verknüpfung mit den Papieren, auf denen die Algorithmen basieren.

Wie ich bereits sagte, können Sie in diesen Fällen wahrscheinlich mit der Verwendung von Listen davonkommen, aber das fügt noch eine weitere Komplexitätsebene hinzu, zusätzlich zu den bereits komplexen Algorithmen.

3
Dunk

Nun, ich habe in einem Spiel, das ich geschrieben habe, eine Verwendung für Arrays gefunden. Ich habe es verwendet, um ein Inventarsystem mit einer festen Anzahl von Slots zu erstellen. Dies hatte mehrere Vorteile:

  1. Ich wusste genau, wie viele offene Inventar-Slots das Spielobjekt hatte, indem ich sah und sah, welche Slots null waren.
  2. Ich wusste genau, in welchem ​​Index sich die einzelnen Elemente befanden.
  3. Es war immer noch ein "typisiertes" Array (Item [] Inventory), so dass ich Objekte vom Typ "Item" hinzufügen/entfernen konnte.

Ich dachte mir, wenn ich jemals das Inventar "vergrößern" müsste, könnte ich dies tun, indem ich die alten Elemente in das neue Array übertrage. Da das Inventar jedoch durch den Bildschirmbereich fixiert war und ich es nicht dynamisch vergrößern musste/kleiner, es funktionierte gut für den Zweck, für den ich es verwendet habe.

1
m t

Wenn Sie alle Elemente einer Liste durchlaufen, ist ein Array nicht erforderlich. Die nächste oder willkürliche Auswahl ohne Ersatz reicht aus.

Wenn Ihr Algorithmus jedoch zufälligen Zugriff auf die Elemente in der Sammlung benötigt, ist ein Array erforderlich.

Dies ist etwas analog zu "ist goto notwendig?". In einer vernünftigen modernen Sprache wird es überhaupt nicht benötigt. Wenn Sie jedoch die Abstraktionen abziehen, ist dies alles, was Ihnen tatsächlich zur Verfügung steht. Das heißt, die einzige Möglichkeit, diese Abstraktionen zu implementieren, besteht in der Funktion "Unnötig". (Natürlich ist die Analogie nicht perfekt, ich glaube nicht, dass jemand sagt, dass Arrays eine schlechte Programmierpraxis sind; sie sind leicht zu verstehen und zu überlegen).

1
Mitch

Legacy-Kompatibilität.

Alle bilden persönliche Erfahrung:

Legacy-Programmierer - mein Kollege verwendet Arrays überall, seit über 30 Jahren, viel Glück beim Umdenken mit Ihren neuen Ideen.

Legacy-Code - foo (Array-Leiste []) sicher, dass Sie eine Listen-/Vektor-/Sammlungs-Toarray-Funktion verwenden können, aber wenn Sie keine der zusätzlichen Funktionen verwenden, ist es einfacher, ein Array zu verwenden, das häufig besser lesbar ist, ohne dass der Typ wechselt.

Legacy-Chefin - meine Chefin war eine gute Programmiererin, bevor sie vor vielen Jahren ins Management ging, und glaubt immer noch, dass sie auf dem neuesten Stand ist. "Verwenden von Arrays" kann ein Meeting beenden und erklären, was eine Sammlung für jeden das Mittagessen kosten kann.

0
Skeith

1) Es gibt keine mehrdimensionale Version von List. Wenn Ihre Daten mehr als eine Dimension haben, ist die Verwendung von Listen sehr ineffizient.

2) Wenn Sie mit einer großen Anzahl kleiner Datentypen arbeiten (z. B. einer Karte, auf der Sie nur ein Byte für den Geländetyp haben), kann es aufgrund des Cachings zu erheblichen Leistungsunterschieden kommen. Die Array-Version lädt mehrere Elemente pro gelesenem Speicher, die Listenversion lädt nur eines. Darüber hinaus enthält die Array-Version mehrmals so viele Zellen im Cache wie die Listenversion. Wenn Sie die Daten wiederholt verarbeiten, kann dies einen großen Unterschied machen, wenn die Array-Version in den Cache passt, die Listenversion jedoch nicht.

Betrachten Sie für einen extremen Fall Minecraft. (Ja, es ist nicht in C # geschrieben. Der gleiche Grund gilt.)

0
Loren Pechtel

Ein Array mit 100 Elementen eines Typs T kapselt 100 unabhängige Variablen des Typs T. Wenn T zufällig ein Werttyp ist, der ein veränderliches öffentliches Feld vom Typ Q und eines vom Typ R aufweist, kapselt jedes Element des Arrays unabhängige Variablen Das Array als Ganzes kapselt somit 100 unabhängige Variablen vom Typ Q und 100 unabhängige Variablen vom Typ R ein. Auf jede dieser Variablen kann einzeln zugegriffen werden, ohne andere zu beeinflussen. Kein anderer Sammlungstyp als Arrays kann die Verwendung von Strukturfeldern als unabhängige Variablen ermöglichen.

Wenn T stattdessen ein Klassentyp mit öffentlichen veränderlichen Feldern vom Typ Q und R war, enthält jedes Element des Arrays die nur Referenz an einer beliebigen Stelle im Universum auf eine Instanz von T, und wenn keines der Elemente des Arrays jemals geändert wird, um ein Objekt zu identifizieren, auf das eine externe Referenz existiert, kapselt das Array effektiv 100 unabhängige Variablen vom Typ Q und 100 unabhängige Variablen vom Typ R. Andere Sammlungstypen können ahmen das Verhalten eines solchen Arrays nach, aber wenn der einzige Zweck des Arrays darin besteht, 100 Variablen vom Typ Q und 100 vom Typ R zu kapseln, ist das Einkapseln jedes Variablenpaars in ein eigenes Klassenobjekt eine teure Methode. Ferner erzeugt die Verwendung eines Arrays oder einer Sammlung veränderlicher Klassentypen die Möglichkeit, dass die durch Array-Elemente identifizierten Variablen möglicherweise nicht unabhängig sind.

Wenn sich ein Typ wie ein Objekt verhalten soll, sollte es sich entweder um einen Klassentyp oder um eine private Feldstruktur handeln, die keine andere Möglichkeit der Mutation als das Ersetzen bietet. Wenn sich ein Typ jedoch wie eine Reihe verwandter, aber unabhängiger Variablen verhalten soll, die mit Klebeband zusammenkleben, sollte man einen Typ verwenden, der is eine Reihe von Variablen ist, die mit Klebeband zusammengeklebt sind - eine exponierte Feldstruktur. Arrays dieser Art sind sehr effizient zu bearbeiten und haben eine sehr saubere Semantik. Die Verwendung eines anderen Typs führt zu einer durcheinandergebrachten Semantik, einer schlechteren Leistung oder beidem.

0
supercat

Ein wichtiger Unterschied ist die Speicherzuordnung. Das Durchlaufen einer verknüpften Liste kann beispielsweise zu vielen Cache-Fehlern und einer langsameren Leistung führen, während ein Array einen zusammenhängenden Speicherblock darstellt, der mehrere Instanzen eines bestimmten Datentyps enthält, und das Durchlaufen in der richtigen Reihenfolge die CPU eher trifft Zwischenspeicher.

Natürlich kann ein Array von Objektreferenzen nicht so stark von Cache-Treffern profitieren, da die Dereferenzierung Sie immer noch überall im Speicher hinführen kann.

Dann gibt es Listenimplementierungen wie ArrayList, die eine Liste mithilfe eines Arrays implementieren. Sie sind nützliche Grundelemente.

0
Rory Hunter