C # equivalente del vector C ++, con memoria contigua?

85

¿Cuál es el equivalente en C # del vector C ++?

Estoy buscando esta característica:

Tener una matriz dinámica de memoria almacenada de forma contigua que no tenga una penalización de rendimiento para el acceso frente a las matrices estándar.

Estaba buscando y dicen .NET equivalent to the vector in C++ is the ArrayList, entonces:

¿ArrayList tiene esa característica de memoria contigua?

edgarmtze
fuente
4
¿No está el CLR lo suficientemente cerca del metal para que pueda especificar (o incluso esperar constantemente) cómo se asigna una estructura en la memoria?
Aphex

Respuestas:

101

Puede usar un List<T>y cuando Tes un tipo de valor, se asignará en la memoria contigua, lo que no sería el caso si fuera Tun tipo de referencia.

Ejemplo:

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

int someElement = integers[1];
Darin Dimitrov
fuente
2
@cMinor, la documentación de la List<T>clase contiene muchos ejemplos pero he actualizado mi respuesta para incluir uno.
Darin Dimitrov
5
No estoy 100% familiarizado con CLR, pero tiene sentido que incluso si Tes un tipo de referencia, todavía tendrá memoria contigua. Es básicamente una serie de consejos ...
josaphatv
"que no sería el caso si T es un tipo de referencia" - es tanto el caso como para T[]... el OP pidió "sin penalización de rendimiento para el acceso frente a matrices estándar", y lo List<T>proporciona. Y si Tes un tipo de referencia, eso es análogo a T*en C ++, por lo que obtiene tanta contigüidad como en C ++. Si uno quiere que los objetos en sí sean contiguos, entonces, por supuesto, necesita tipos de valores ... en ambos idiomas. La diferencia, por supuesto, es que en C ++ cualquier tipo puede usarse como valor o como referencia, mientras que en C # es una propiedad del tipo a través de la distinción clase / estructura.
Jim Balter
Aprendí algo hoy. Pensé List<T>que siempre se implementa como una lista vinculada internamente. Entonces, ¿cómo se expande dinámicamente cuando llamamos Add()? ¿Algo como VB6 Redim Preserveque solía copiar toda la matriz a una nueva ubicación?
dotNET
@dotNet, List<T>crea internamente una pequeña matriz T[]. Los elementos se agregan internamente a la matriz. Una vez que se completa el tamaño de la matriz, se crea una nueva matriz con el doble de tamaño que la anterior. Los datos se copian en la nueva matriz más grande, la más pequeña se destruye y así sucesivamente. Un desarrollador puede dar una pista para .NET para crear una matriz interna lo suficientemente grande antes de llenar la List vía constructor: new List<T>(expected_array_size).
Artru
16

utilizar List<T>. Internamente, utiliza matrices y las matrices utilizan memoria contigua.

Bala R
fuente
2
No es del todo cierto. Si T es un tipo de referencia, no habrá memoria contigua.
Matteo Mosca
2
@Matteo si miras la fuente, hay private T[] _items;que se usa para el almacenamiento de backend, tipo de referencia o no.
Bala R
13
Bueno, eso ya lo sé. Pero dime. Tienes una List <SomeClass>. Las referencias a las instancias de SomeClass se almacenarán en la memoria contigua, pero no las instancias en sí. Como tipos de referencia, estarán en el montón, y seguramente sabes cómo funciona el montón.
Matteo Mosca
@MatteoMosca almacena las referencias contiguas al menos elimina un nivel de indirección. Mejor que nada, supongo.
Tim Seguine
7
@MatteoMosca El OP pidió "ninguna penalización de rendimiento para el acceso frente a las matrices estándar". Eso es cierto para List <T> independientemente de lo que sea T, por lo que todos sus comentarios en esta página están fuera de lugar.
Jim Balter
16

En primer lugar, manténgase alejado de Arraylisto Hashtable. Esas clases deben considerarse obsoletas en favor de los genéricos. Todavía están en el idioma para propósitos heredados.

Ahora, lo que buscas es la List<T>clase. Tenga en cuenta que si T es un tipo de valor, tendrá memoria contiguos, pero no si T es un tipo de referencia, por razones obvias.

Matteo Mosca
fuente
14

C # tiene muchos tipos de referencia. Incluso si un contenedor almacena las referencias de forma contigua, los objetos mismos pueden estar dispersos por el montón

Armen Tsirunyan
fuente