749 Stimmen

Array versus Liste<T>: Wann ist was zu verwenden?

MyClass[] array;
List<MyClass> list;

Welche Szenarien gibt es, in denen das eine dem anderen vorzuziehen ist? Und warum?

13 Stimmen

Arrays sind eher veraltet, wie in einem beliebte Diskussion hier. Auch hier hervorgehoben und von unserem Gastgeber im Blog .

11 Stimmen

Wenn ich mich nicht irre, hat die List<> ein Array als interne Struktur. Immer wenn das interne Array gefüllt ist, wird der Inhalt einfach in ein Array kopiert, das doppelt so groß ist (oder eine andere Konstante, die die aktuelle Größe angibt). de.wikipedia.org/wiki/Dynamische_Anordnung

0 Stimmen

Ykok: Was du sagst, scheint zu stimmen, ich habe den Quellcode von Liste<> hier .

733voto

Marc Gravell Punkte 970173

In der Realität ist es selten, dass Sie ein Array verwenden möchten. Verwenden Sie auf jeden Fall ein List<T> jedes Mal, wenn Sie Daten hinzufügen/entfernen wollen, da die Größenänderung von Arrays teuer ist. Wenn Sie wissen, dass die Daten eine feste Länge haben, und Sie eine Mikro-Optimierung für einige sehr spezifisch Grund (nach dem Benchmarking), dann kann ein Array nützlich sein.

List<T> bietet eine Los mehr Funktionalität als ein Array (obwohl LINQ es ein wenig ausgleicht), und ist fast immer die richtige Wahl. Außer für params Argumente, natürlich. ;-p

Als Gegenleistung - List<T> eindimensional ist; wogegen Sie rechteckige (usw.) Arrays haben wie int[,] o string[,,] - aber es gibt andere Möglichkeiten, solche Daten in einem Objektmodell zu modellieren (falls erforderlich).

Siehe auch:

Trotzdem mache ich eine Los der Verwendung von Arrays in meinem protobuf-net Projekt; ausschließlich für Leistung:

  • wird eine Menge Bit-Shifting durchgeführt, so dass ein byte[] ist für die Kodierung so gut wie unverzichtbar;
  • Ich verwende ein lokales Walzwerk byte[] Puffer, den ich fülle, bevor ich ihn an den zugrunde liegenden Stream (und v.v.) weiterleite; schneller als BufferedStream usw;
  • verwendet es intern ein Array-basiertes Modell von Objekten ( Foo[] statt List<Foo> ), da die Größe nach der Erstellung feststeht und sehr schnell sein muss.

Aber das ist definitiv eine Ausnahme; für die allgemeine Geschäftsabwicklung ist eine List<T> gewinnt jedes Mal.

14 Stimmen

Das Argument der Größenanpassung ist absolut berechtigt. Die Leute bevorzugen jedoch Listen, auch wenn keine Größenanpassung erforderlich ist. Gibt es für diesen letzten Fall ein stichhaltiges, logisches Argument oder ist es nichts weiter als "Arrays sind aus der Mode"?

0 Stimmen

@Frederick: Schwer zu beantworten, ohne das "Warum" zu hören. Eigentlich würde ich in vielen Fällen bevorzugen IList<T> o IEnumerable<T> - überlässt es dem Anrufer, was er verwenden möchte ( T[] o List<T> usw.). LINQ gleicht einen großen Teil der zusätzlichen List<T> Funktionen (über IList<T> ).

1 Stimmen

Eigentlich arbeite ich mit einem Legacy, C# 1.0 Codebase. Einige der Funktionen dort nehmen und zurückgeben Arrays. Keine Größenänderung oder irgendetwas ist passiert....

139voto

Jon Skeet Punkte 1325502

Ich wollte eigentlich nur einen Link hinzufügen, von dem ich überrascht bin, dass er noch nicht erwähnt wurde: Erics Lippert's Blogeintrag über "Arrays gelten als eher schädlich".

Wie Sie dem Titel entnehmen können, wird empfohlen, Sammlungen zu verwenden, wo immer es praktisch ist - aber wie Marc zu Recht betont, gibt es viele Stellen, an denen ein Array wirklich die einzige praktische Lösung ist.

2 Stimmen

Nach über 3 Jahren bin ich endlich dazu gekommen, dies zu lesen, haha. Guter Artikel damals, guter Artikel heute :)

25voto

Alnitak Punkte 324207

Ungeachtet der anderen Antworten, in denen empfohlen wird List<T> werden Sie bei der Bearbeitung Arrays verwenden wollen:

  • Bild-Bitmap-Daten
  • andere Datenstrukturen auf niedriger Ebene (z. B. Netzwerkprotokolle)

1 Stimmen

Warum bei Netzwerkprotokollen? Würden Sie hier nicht lieber benutzerdefinierte Strukturen verwenden und ihnen einen speziellen Serializer oder ein explizites Speicherlayout geben? Außerdem: Was spricht gegen die Verwendung eines List<T> als ein Byte-Array?

11 Stimmen

@Konrad - nun, für den Anfang, Stream.Read und Stream.Write arbeiten mit byte[], sowie Encoding usw...

15voto

Spencer Ruport Punkte 34547

Wenn Sie sich nicht wirklich Sorgen um die Leistung machen, und damit meine ich: "Warum benutzen Sie .Net und nicht C++?", sollten Sie bei List<> bleiben. Es ist einfacher zu pflegen und erledigt die ganze schmutzige Arbeit der Größenänderung eines Arrays hinter den Kulissen für Sie. (Falls nötig, ist List<> ziemlich schlau bei der Wahl der Array-Größen, so dass es das normalerweise nicht braucht.)

22 Stimmen

"Warum verwenden Sie .Net statt C++?" XNA

2 Stimmen

Um auf den Kommentar von @Bengt einzugehen: Leistung ist nicht die Priorität von .NET, und das ist durchaus fair. Aber einige kluge Köpfe dachten an die Verwendung von .NET mit Spiel-Engines. In der Tat verwenden die meisten Spiele-Engines heutzutage C#. In dieser Hinsicht ist Unity 3D das Paradigma für "Wenn eine Spiele-Engine nicht für AAA gedacht war".

2 Stimmen

@mireazma Das ist schon lange keine gültige Aussage mehr (in Bezug auf Unity). Über HPC# und Burst erhalten wir C++-Leistung aus C#. Ein großer Teil der Engine-Interna wird nach C# migriert. Selbst wenn es sich um ein Spieleskript in einem Nicht-DOTS-Projekt handelt, leistet IL2CPP sehr, sehr gute Arbeit bei der Erstellung von performantem Code.

11voto

Herman Schoenfeld Punkte 7934

Arrays debe anstelle von List verwendet werden, wenn die Unveränderlichkeit der Sammlung selbst Teil des Vertrags zwischen dem Client- und dem Provider-Code ist (nicht unbedingt die Unveränderlichkeit der Elemente innerhalb der Sammlung) UND wenn IEnumerable nicht geeignet ist.

Zum Beispiel,

var str = "This is a string";
var strChars = str.ToCharArray();  // returns array

Es ist klar, dass eine Änderung von "strChars" das ursprüngliche "str"-Objekt nicht verändert, unabhängig von der Kenntnis des zugrunde liegenden Typs von "str" auf Implementierungsebene.

Aber angenommen, dass

var str = "This is a string";
var strChars = str.ToCharList();  // returns List<char>
strChars.Insert(0, 'X');

In diesem Fall geht aus dem Codeausschnitt allein nicht hervor, ob die Insert-Methode das ursprüngliche "str"-Objekt verändern wird oder nicht. Es erfordert Kenntnisse auf der Implementierungsebene von String, um diese Entscheidung zu treffen, was den Design by Contract-Ansatz bricht. Im Fall von String ist das keine große Sache, aber es kann in fast jedem anderen Fall eine große Sache sein. Das Einstellen der Liste auf schreibgeschützt hilft zwar, führt aber zu Laufzeitfehlern, nicht zur Kompilierzeit.

1 Stimmen

Ich bin relativ neu in C#, aber es ist nicht klar für mich, warum die Rückgabe einer Liste Mutabilität der ursprünglichen Daten in einer Weise, die Rückgabe eines Arrays nicht vorschlagen würde. Ich hätte gedacht, dass eine Methode, deren Name beginnt mit To wird ein Objekt erstellen, das die ursprüngliche Instanz nicht verändern kann, im Gegensatz zu strChars as char[] was, wenn es gültig ist, bedeuten würde, dass Sie jetzt in der Lage sind, das ursprüngliche Objekt zu ändern.

0 Stimmen

@TimMB Es gibt die Unveränderlichkeit der Sammlung (es können keine Elemente hinzugefügt oder entfernt werden) und die Unveränderlichkeit der Elemente in der Sammlung. Ich habe mich auf Letzteres bezogen, während Sie wahrscheinlich beides miteinander verwechseln. Die Rückgabe eines Arrays garantiert dem Client, dass er keine Elemente hinzufügen oder entfernen kann. Falls doch, wird das Array neu zugewiesen und es wird sichergestellt, dass es keine Auswirkungen auf das Original hat. Bei der Rückgabe einer Liste gibt es keine solche Zusicherung und das Original könnte betroffen sein (hängt von der Implementierung ab). Das Ändern von Elementen innerhalb der Sammlung (ob Array oder Liste) könnte das Original beeinflussen, wenn der Typ des Elements keine Struktur ist.

0 Stimmen

Ich danke Ihnen für die Klarstellung. Ich bin immer noch verwirrt (wahrscheinlich, weil ich aus der C++-Welt komme). Wenn str verwendet intern ein Array und ToCharArray einen Verweis auf dieses Array zurückgibt, kann der Client die str durch Ändern der Elemente dieses Feldes, auch wenn die Größe gleich bleibt. Sie schreiben jedoch: "Es ist klar, dass eine Änderung von "strChars" das ursprüngliche "str"-Objekt nicht verändert". Was übersehe ich hier? Soweit ich das sehe, kann der Client in beiden Fällen auf die interne Darstellung zugreifen, und das würde unabhängig vom Typ eine Mutation in irgendeiner Form ermöglichen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X