.NET ofrece un contenedor de lista genérico cuyo rendimiento es casi idéntico (consulte la pregunta Rendimiento de matrices frente a listas). Sin embargo, son bastante diferentes en la inicialización.
Las matrices son muy fáciles de inicializar con un valor predeterminado y, por definición, ya tienen cierto tamaño:
string[] Ar = new string[10];
Lo que permite a uno asignar de forma segura elementos aleatorios, digamos:
Ar[5]="hello";
con la lista, las cosas son más complicadas. Puedo ver dos formas de hacer la misma inicialización, ninguna de las cuales es lo que llamarías elegante:
List<string> L = new List<string>(10);
for (int i=0;i<10;i++) L.Add(null);
o
string[] Ar = new string[10];
List<string> L = new List<string>(Ar);
¿Cuál sería una forma más limpia?
EDITAR: Las respuestas hasta ahora se refieren a la capacidad, que es algo más que rellenar previamente una lista. Por ejemplo, en una lista recién creada con una capacidad de 10, no se puede hacerL[2]="somevalue"
EDICIÓN 2: La gente se pregunta por qué quiero usar las listas de esta manera, ya que no es la forma en que deben usarse. Puedo ver dos razones:
Se podría argumentar de manera bastante convincente que las listas son los arreglos de la "próxima generación", lo que agrega flexibilidad sin casi ninguna penalización. Por lo tanto, uno debería usarlos por defecto. Estoy señalando que es posible que no sean tan fáciles de inicializar.
Lo que estoy escribiendo actualmente es una clase base que ofrece una funcionalidad predeterminada como parte de un marco más grande. En la funcionalidad predeterminada que ofrezco, el tamaño de la Lista se conoce de manera avanzada y, por lo tanto, podría haber usado una matriz. Sin embargo, quiero ofrecer a cualquier clase base la posibilidad de ampliarla dinámicamente y, por tanto, opto por una lista.
List
no es un reemplazo paraArray
. Resuelven problemas claramente separados. Si quieres un tamaño fijo, quieres unArray
. Si usa unList
, lo está haciendo mal.Respuestas:
No puedo decir que necesite esto muy a menudo, ¿podría dar más detalles sobre por qué quiere esto? Probablemente lo pondría como un método estático en una clase auxiliar:
Usted podría utilizar
Enumerable.Repeat(default(T), count).ToList()
, pero que podría ser debido ineficaz para amortiguar el cambio de tamaño.Tenga en cuenta que si
T
es un tipo de referencia, almacenarácount
copias de la referencia pasada para elvalue
parámetro, por lo que todas harán referencia al mismo objeto. Eso puede ser o no lo que desea, dependiendo de su caso de uso.EDITAR: Como se señaló en los comentarios, puede
Repeated
usar un bucle para completar la lista si lo desea. Eso también sería un poco más rápido. Personalmente, el código me pareceRepeat
más descriptivo y sospecho que en el mundo real la diferencia de rendimiento sería irrelevante, pero su kilometraje puede variar.fuente
Enumerable.Repeat(...).ToArray()
, que no es como lo estoy usando.Enumerable.Repeat()
de la siguiente manera (implementadoPair
como el equivalente de C ++):Enumerable.Repeat( new Pair<int,int>(int.MaxValue,-1), costs.Count)
notando el efecto secundario, queList
estaba lleno de copias referenciadas a un solo objeto. Cambiar un elemento comomyList[i].First = 1
cambió cada elemento del todoList
. Me tomó horas encontrar este error. ¿Conocen alguna solución a este problema (excepto por el uso de un bucle común y el uso.Add(new Pair...)
?)fuente
L
simplemente reutilizará la memoriastring[10]
tal como está (el almacenamiento de respaldo de una lista también es una matriz) o asignará una nueva memoria propia y luego copiará el contenido destring[10]
?string[10]
obtendrá la basura recolectada automáticamente siL
selecciona la ruta posterior.Utilice el constructor que toma un int ("capacidad") como argumento:
EDITAR: Debo agregar que estoy de acuerdo con Frederik. Está usando la Lista de una manera que va en contra de todo el razonamiento detrás de su uso en primer lugar.
EDIT2:
¿Por qué alguien necesitaría saber el tamaño de una lista con todos los valores nulos? Si no hay valores reales en la lista, esperaría que la longitud sea 0. De todos modos, el hecho de que esto sea complicado demuestra que va en contra del uso previsto de la clase.
fuente
new List<string>()
que respecta al problema. . Bien hecho por conseguir tantos votos positivos :)list[index] = obj;
y usar algunas otras capacidades de lista.Cree una matriz con la cantidad de elementos que desee primero y luego convierta la matriz en una Lista.
fuente
¿Por qué utiliza una lista si desea inicializarla con un valor fijo? Puedo entender que, por el bien del rendimiento, desea darle una capacidad inicial, pero ¿no es una de las ventajas de una lista sobre una matriz regular que puede crecer cuando sea necesario?
Cuando haces esto:
Creas una lista cuya capacidad es de 100 enteros. Esto significa que su Lista no necesitará "crecer" hasta que agregue el elemento 101. La matriz subyacente de la lista se inicializará con una longitud de 100.
fuente
Inicializar el contenido de una lista como esa no es realmente para lo que sirven las listas. Las listas están diseñadas para contener objetos. Si desea asignar números particulares a objetos particulares, considere usar una estructura de par clave-valor como una tabla hash o un diccionario en lugar de una lista.
fuente
Parece estar enfatizando la necesidad de una asociación posicional con sus datos, entonces, ¿no sería más apropiado un arreglo asociativo?
fuente
Si desea inicializar la lista con N elementos de algún valor fijo:
fuente
Puede usar Linq para inicializar inteligentemente su lista con un valor predeterminado. (Similar a la respuesta de David B. )
Vaya un paso más allá e inicialice cada cadena con valores distintos "cadena 1", "cadena 2", "cadena 3", etc.
fuente
fuente
La respuesta aceptada (la que tiene la marca de verificación verde) tiene un problema.
El problema:
Recomiendo cambiar la línea de arriba para realizar una copia del objeto. Hay muchos artículos diferentes sobre eso:
Si desea inicializar todos los elementos de su lista con el constructor predeterminado, en lugar de NULL, agregue el siguiente método:
fuente
Un aviso sobre IList: MSDN IList Comentarios : "Las implementaciones de IList se dividen en tres categorías: solo lectura, tamaño fijo y tamaño variable. (...). Para obtener la versión genérica de esta interfaz, consulte
System.Collections.Generic.IList<T>
."IList<T>
NO hereda deIList
(peroList<T>
implementa ambosIList<T>
yIList
), pero siempre es de tamaño variable . Desde .NET 4.5, también tenemos,IReadOnlyList<T>
pero AFAIK, no hay una Lista genérica de tamaño fijo que sea lo que está buscando.fuente
Esta es una muestra que utilicé para mi prueba unitaria. Creé una lista de objetos de clase. Luego usé forloop para agregar una cantidad 'X' de objetos que espero del servicio. De esta forma, puede agregar / inicializar una lista para cualquier tamaño dado.
Espero haber sido de ayuda para ustedes.
fuente
Un poco tarde, pero la primera solución que propuso me parece mucho más limpia: no asigna memoria dos veces. Incluso el constrcutor de List necesita recorrer la matriz para copiarla; ni siquiera sabe de antemano que solo hay elementos nulos en su interior.
1. - asignar N - loop N Costo: 1 * asignar (N) + N * loop_iteration
2. - asignar N - asignar N + bucle () Costo: 2 * asignar (N) + N * loop_iteration
Sin embargo, la asignación de bucles de List puede ser más rápida ya que List es una clase incorporada, pero C # está compilado con jit tan ...
fuente