MyClass[] array;
List<MyClass> list;
Welche Szenarien gibt es, in denen das eine dem anderen vorzuziehen ist? Und warum?
MyClass[] array;
List<MyClass> list;
Welche Szenarien gibt es, in denen das eine dem anderen vorzuziehen ist? Und warum?
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:
byte[]
ist für die Kodierung so gut wie unverzichtbar;byte[]
Puffer, den ich fülle, bevor ich ihn an den zugrunde liegenden Stream (und v.v.) weiterleite; schneller als BufferedStream
usw;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.
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"?
@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>
).
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....
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.
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?
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.)
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".
@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.
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.
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.
@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.
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 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.
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 .
42 Stimmen
@gimel Die Behauptung, dass Arrays veraltet sind, ist vielleicht ein wenig gewagt