C # -Äquivalent des C ++ - Vektors mit zusammenhängendem Speicher?

85

Was ist das C # -Äquivalent des C ++ - Vektors?

Ich suche nach dieser Funktion:

Ein dynamisches Array von zusammenhängend gespeichertem Speicher ohne Leistungseinbußen für den Zugriff im Vergleich zu Standard-Arrays.

Ich habe gesucht und sie sagen .NET equivalent to the vector in C++ is the ArrayList, also:

Verfügt ArrayList über diese zusammenhängende Speicherfunktion?

edgarmtze
quelle
4
Ist die CLR nicht unzureichend nahe am Metall, um anzugeben (oder sogar konsequent zu erwarten), wie eine Struktur im Speicher zugewiesen wird?
Aphex

Antworten:

101

Sie können einen verwenden, List<T>und wenn Tes sich um einen Werttyp handelt, wird dieser im zusammenhängenden Speicher zugewiesen, was bei Teinem Referenztyp nicht der Fall wäre .

Beispiel:

List<int> integers = new List<int>();
integers.Add(1);
integers.Add(4);
integers.Add(7);

int someElement = integers[1];
Darin Dimitrov
quelle
2
@cMinor, die Dokumentation der List<T>Klasse enthält viele Beispiele, aber ich habe meine Antwort aktualisiert, um eines aufzunehmen.
Darin Dimitrov
5
Ich bin nicht zu 100% mit der CLR vertraut, aber es ist sinnvoll, dass Sie auch dann Teinen zusammenhängenden Speicher haben , wenn es sich um einen Referenztyp handelt. Es ist im Grunde eine Reihe von Zeigern ...
Josaphatv
"Was nicht der Fall wäre, wenn T ein Referenztyp ist" - es ist genauso der Fall wie für T[]... das OP forderte "keine Leistungseinbußen für den Zugriff im Vergleich zu Standard-Arrays" und List<T>stellt dies bereit. Und wenn Tes sich um einen Referenztyp handelt, der analog zu T*C ++ ist, erhalten Sie genau so viele Zusammenhänge wie in C ++. Wenn man möchte, dass die Objekte selbst zusammenhängend sind, braucht man natürlich Werttypen ... in beiden Sprachen. Der Unterschied besteht natürlich darin, dass in C ++ jeder Typ entweder als Wert oder als Referenz verwendet werden kann, während er in C # über die Klassen- / Strukturunterscheidung eine Eigenschaft des Typs ist.
Jim Balter
Habe heute etwas gelernt. Ich dachte, es List<T>wird immer intern als verknüpfte Liste implementiert. Wie dehnt es sich dann dynamisch aus, wenn wir anrufen Add()? So etwas wie VB6s, mit Redim Preservedenen das gesamte Array an einen neuen Speicherort kopiert wurde?
DotNET
@dotNet List<T>erstellt intern ein kleines Array T[]. Die Elemente werden intern zum Array hinzugefügt. Sobald die Größe des Arrays abgeschlossen ist, wird ein neues Array erstellt, das doppelt so groß ist wie das vorherige. Die Daten werden in das neue größere Array kopiert, das kleinere wird zerstört und so weiter. Ein Entwickler kann .NET einen Hinweis geben, um ein ausreichend großes internes Array zu erstellen, bevor er den List Via-Konstruktor ausfüllt : new List<T>(expected_array_size).
Artru
16

verwenden List<T>. Intern werden Arrays verwendet, und Arrays verwenden zusammenhängenden Speicher.

Bala R.
quelle
2
Nicht ganz richtig. Wenn T ein Referenztyp ist, gibt es keinen zusammenhängenden Speicher.
Matteo Mosca
2
@Matteo Wenn Sie sich die Quelle ansehen, gibt es private T[] _items;diese, die für den Backend-Speicher verwendet wird, Referenztyp oder nicht.
Bala R
13
Nun, das weiß ich. Aber sag mir. Sie haben eine Liste <SomeClass>. Die Verweise auf die SomeClass-Instanzen werden im zusammenhängenden Speicher gespeichert, nicht jedoch auf die Instanzen selbst. Als Referenztypen befinden sie sich im Heap, und Sie wissen sicherlich, wie der Heap funktioniert.
Matteo Mosca
@MatteoMosca, das die Referenzen zusammenhängend speichert, entfernt mindestens eine Indirektionsebene. Besser als nichts, denke ich.
Tim Seguine
7
@MatteoMosca Das OP forderte "keine Leistungseinbußen beim Zugriff im Vergleich zu Standard-Arrays". Dies gilt für List <T>, unabhängig davon, was T ist. Alle Ihre Kommentare auf dieser Seite sind daher falsch.
Jim Balter
16

Halten Sie sich zunächst von Arraylistoder fern Hashtable. Diese Klassen gelten zugunsten von Generika als veraltet. Sie sind immer noch in der Sprache für Legacy-Zwecke.

Was Sie jetzt suchen, ist die List<T>Klasse. Beachten Sie, dass Sie, wenn T ein Werttyp ist, aus offensichtlichen Gründen über einen Contiguos-Speicher verfügen, nicht jedoch, wenn T ein Referenztyp ist.

Matteo Mosca
quelle
14

C # hat viele Referenztypen. Selbst wenn ein Container die Referenzen zusammenhängend speichert , können die Objekte selbst über den Heap verstreut sein

Armen Tsirunyan
quelle