Matriz versus Lista : ¿Cuándo usar qué?

MyClass[] array; List list; 

¿Cuáles son los escenarios cuando uno es preferible sobre el otro? ¿Y por qué?

En realidad, es raro que desee utilizar una matriz. Definitivamente use una List cada vez que quiera agregar / eliminar datos, ya que el redimensionamiento de las matrices es costoso. Si sabe que los datos son de longitud fija, y quiere micro-optimizar por alguna razón muy específica (después de la evaluación comparativa), entonces una matriz puede ser útil.

List ofrece mucha más funcionalidad que un array (aunque LINQ lo iguala un poco), y casi siempre es la elección correcta. Excepto por los argumentos de params , por supuesto. ;-pag

Como un contador – List es unidimensional; donde -como usted tiene arrays rectangulares (etc) como int[,] o string[,,] – pero hay otras formas de modelar tales datos (si es necesario) en un modelo de objetos.

Ver también:

  • ¿Cómo / cuándo abandonar el uso de matrices en c # .net?
  • Arrays, ¿cuál es el punto?

Dicho esto, aprovecho mucho las matrices en mi proyecto protobuf-net ; completamente para el rendimiento:

  • hace un montón de cambios de bit, por lo que un byte[] es bastante esencial para la encoding;
  • Utilizo un buffer local de byte[] que llené antes de enviarlo al flujo subyacente (y vv); más rápido que BufferedStream etc;
  • internamente utiliza un modelo de objetos basado en matrices ( Foo[] lugar de List ), ya que el tamaño se fija una vez creado y debe ser muy rápido.

Pero esta es definitivamente una excepción; para el procesamiento general de la línea de negocio, una List gana cada vez.

Realmente, el solo hecho de responder para agregar un enlace que estoy sorprendido no se ha mencionado aún: la entrada del blog de Eric Lippert en “Arrays consideró algo perjudicial”.

Puede juzgar por el título que sugiere utilizar colecciones siempre que sea práctico, pero como señala correctamente Marc, hay muchos lugares en los que una matriz es realmente la única solución práctica.

Use una matriz cuando trate con datos que sean:

  • de tamaño fijo, o es poco probable que crezca mucho
  • adecuadamente grande (más de 10, 50, 100 elementos, según el algoritmo)
  • lo indexarás mucho, es decir, sabes que a menudo querrás el tercer elemento, o el quinto, o lo que sea.

Use una lista para:

  • listas de datos de longitud variable
  • que se usan principalmente como una stack o una cola o necesitan repetirse en su totalidad
  • cuando no quiere escribir una expresión para derivar el tamaño máximo de la matriz para la statement y no quiere perder un gran número

Use un hashmap para:

  • listas de datos de longitud variable
  • que necesitan ser indexados como una matriz

En realidad, querrá una lista o hashmap casi todo el tiempo. La próxima vez que elija una estructura de datos, piense en lo que debe hacer para usted (o su código, de todos modos). Luego elige algo basado en eso. En caso de duda, elija algo tan general como sea posible, es decir, una interfaz que pueda reemplazar fácilmente la implementación. Algunos buenos enlaces en las otras respuestas también.

A pesar de las otras respuestas que recomiendan List , querrá usar arrays cuando maneje:

  • datos de bitmap de imagen
  • otras estructuras de datos de bajo nivel (es decir, protocolos de red)

A menos que estés realmente preocupado por el rendimiento, y con eso quiero decir, “¿Por qué estás usando .Net en lugar de C ++?” debes quedarte con List <>. Es más fácil de mantener y hace todo el trabajo sucio de cambiar el tamaño de una matriz detrás de escena para usted. (Si es necesario, List <> es bastante inteligente para elegir los tamaños de matriz, por lo que no suele ser necesario).

Las matrices deben usarse con preferencia a List cuando la inmutabilidad de la colección en sí es parte del contrato entre el código del cliente y el proveedor (no necesariamente la inmutabilidad de los elementos dentro de la colección) Y cuando IEnumerable no es adecuado.

Por ejemplo,

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

Está claro que la modificación de “strChars” no mutará el objeto “str” ​​original, independientemente del conocimiento a nivel de implementación del tipo subyacente “str”.

Pero supongamos que

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

En este caso, no está claro solo de ese fragmento de código si el método insert cambiará o no el objeto original “str”. Requiere conocimiento del nivel de implementación de String para realizar esa determinación, lo que rompe el enfoque de Diseño por contrato. En el caso de String, no es un gran problema, pero puede ser un gran problema en casi cualquier otro caso. Configurar la Lista como de solo lectura ayuda pero da como resultado errores en tiempo de ejecución, no en tiempo de comstackción.

Si sé exactamente cuántos elementos voy a necesitar, digamos que necesito 5 elementos y solo 5 elementos, entonces uso una matriz. De lo contrario, simplemente uso una lista .

La mayoría de las veces, usar una List sería suficiente. Una List utiliza una matriz interna para manejar sus datos y redimensiona automáticamente la matriz al agregar más elementos a la List que su capacidad actual, lo que la hace más fácil de usar que una matriz, donde necesita conocer la capacidad de antemano.

Consulte http://msdn.microsoft.com/en-us/library/ms379570(v=vs.v.80).aspx#datastructures20_1_topic5 para obtener más información sobre las listas en C # o simplemente descompile System.Collections.Generic.List .

Si necesita datos multidimensionales (por ejemplo, usando una matriz o en la progtwigción de gráficos), probablemente optaría por una array .

Como siempre, si la memoria o el rendimiento son un problema, ¡mídelo! De lo contrario, podría estar haciendo suposiciones falsas sobre el código.

Otra situación aún no mencionada es cuando uno tendrá una gran cantidad de elementos, cada uno de los cuales consiste en un conjunto fijo de variables relacionadas pero independientes pegadas juntas (por ejemplo, las coordenadas de un punto o los vértices de un triángulo 3d). Una serie de estructuras de campo expuesto permitirá que sus elementos se modifiquen eficientemente “en su lugar”, algo que no es posible con ningún otro tipo de colección. Debido a que una matriz de estructuras mantiene sus elementos consecutivamente en la RAM, los accesos secuenciales a los elementos de la matriz pueden ser muy rápidos. En situaciones donde el código necesitará hacer muchas pasadas secuenciales a través de una matriz, una matriz de estructuras puede superar a una matriz u otra colección de referencias de objetos de clase por un factor de 2: 1; Además, la capacidad de actualizar elementos en el lugar puede permitir que una matriz de estructuras supere cualquier otro tipo de colección de estructuras.

Aunque las matrices no se pueden redimensionar, no es difícil tener un almacén de códigos una referencia de matriz junto con la cantidad de elementos que están en uso, y reemplazar la matriz con una más grande según sea necesario. Alternativamente, uno podría escribir código fácilmente para un tipo que se comportaba de forma muy similar a List pero exponía su almacén de respaldo, lo que permitía decir MyPoints.Add(nextPoint); o MyPoints.Items[23].X += 5; . Tenga en cuenta que este último no arrojaría necesariamente una excepción si el código intentara acceder más allá del final de la lista, pero el uso sería conceptualmente bastante similar a List .

Las listas en .NET son envoltorios sobre matrices y usan una matriz internamente. La complejidad del tiempo de las operaciones en las listas es la misma que con las matrices, sin embargo, hay un poco más de sobrecarga con toda la funcionalidad agregada / facilidad de uso de las listas (como el cambio de tamaño automático y los métodos que vienen con la clase list). Más o menos, recomendaría usar listas en todos los casos a menos que exista una razón convincente para no hacerlo, como si necesita escribir un código extremadamente optimizado o si está trabajando con otro código que se basa en matrices.

Depende completamente de los contextos en los que se necesita la estructura de datos. Por ejemplo, si está creando elementos para ser usados ​​por otras funciones o servicios usando List, es la manera perfecta de lograrlo.

Ahora, si tiene una lista de elementos y solo desea mostrarlos, por ejemplo, en una matriz de páginas web está el contenedor que necesita usar.

En lugar de pasar por una comparación de las características de cada tipo de datos, creo que la respuesta más pragmática es “las diferencias probablemente no son tan importantes para lo que necesita lograr, especialmente porque ambos implementan IEnumerable , así que sigan las convenciones y el uso popular”. una List hasta que tenga una razón para no hacerlo, en ese momento es probable que tenga su razón para usar una matriz sobre una List . ”

La mayoría de las veces en el código administrado va a querer favorecer que las colecciones sean tan fáciles de trabajar como sea posible, más que preocuparse por las micro-optimizaciones.

Como nadie menciona: MyClass[] y List implementan IList . Si está considerando cuál aceptar como argumento, puede declararlo como IList para la conveniencia de los llamantes. (por ejemplo, Foo(IList foo) se puede llamar como Foo(new[] { 1, 2, 3 }) o Foo(new List { 1, 2, 3 }) )

Pueden ser impopulares, pero soy fanático de las matrices en proyectos de juegos. – La velocidad de iteración puede ser importante en algunos casos, porque una Array tiene mucha menos carga si no haces mucho por elemento. Agregar y eliminar no es tan difícil con las funciones de ayuda. Es más lento, pero en los casos en que solo lo construyes una vez. puede que no importe – En la mayoría de los casos, se desperdicia menos memoria (lo que es realmente significativo con las matrices de estructuras) – Un poco menos de basura y punteros y persiguiendo punteros

Dicho esto, utilizo la Lista mucho más a menudo que las matrices en la práctica, pero cada uno tiene su lugar.

Sería bueno si List incluyera un tipo integrado para que pudieran optimizar el reinicio y la sobrecarga de la enumeración.