¿Cómo inicializar una Lista a un tamaño dado (en contraposición a la capacidad)?

.NET ofrece un contenedor de lista genérico cuyo rendimiento es casi idéntico (consulte la pregunta sobre el rendimiento de las matrices frente a las 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 le permite asignar elementos aleatorios de manera segura, por ejemplo:

 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 L = new List(10); for (int i=0;i<10;i++) L.Add(null); 

o

 string[] Ar = new string[10]; List L = new List(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 completar previamente una lista. Por ejemplo, en una lista recién creada con una capacidad de 10, no se puede hacer L[2]="somevalue"

EDIT 2: La gente se pregunta por qué quiero usar las listas de esta manera, ya que no es la forma en que están destinadas a ser utilizadas. Puedo ver dos razones:

  1. Se podría argumentar de manera bastante convincente que las listas son las matrices de “próxima generación”, agregando flexibilidad casi sin penalización. Por lo tanto, uno debe usarlos por defecto. Estoy señalando que podrían no ser tan fáciles de inicializar.

  2. Lo que estoy escribiendo actualmente es una clase base que ofrece funcionalidad predeterminada como parte de un marco más grande. En la funcionalidad predeterminada que ofrezco, el tamaño de la lista se conoce en avanzado y, por lo tanto, podría haber usado una matriz. Sin embargo, quiero ofrecer a cualquier clase base la posibilidad de extenderla dinámicamente y, por lo tanto, opto por una lista.

No puedo decir que lo necesite con mucha frecuencia. ¿Podría darnos más detalles sobre por qué quiere esto? Probablemente lo pondría como un método estático en una clase de ayuda:

 public static class Lists { public static List RepeatedDefault(int count) { return Repeated(default(T), count); } public static List Repeated(T value, int count) { List ret = new List(count); ret.AddRange(Enumerable.Repeat(value, count)); return ret; } } 

Podría usar Enumerable.Repeat(default(T), count).ToList() pero eso sería ineficiente debido al cambio de tamaño del búfer.

EDITAR: Como se señaló en los comentarios, puede hacer que el uso Repeated un bucle para completar la lista si así lo desea. Eso sería un poco más rápido también. Personalmente encuentro que el código que usa Repeat más descriptivo, y sospecho que en el mundo real la diferencia de rendimiento sería irrelevante, pero su millaje puede variar.

 List L = new List ( new string[10] ); 

Utilice el constructor que toma un int (“capacidad”) como argumento:

 List = new List(10); 

EDITAR: Debo añadir que estoy de acuerdo con Frederik. Está utilizando la Lista de una manera que va en contra de todo el razonamiento detrás de usarla en primer lugar.

EDIT2:

EDIT 2: Lo que estoy escribiendo actualmente es una clase base que ofrece funcionalidad predeterminada como parte de un marco más grande. En la funcionalidad predeterminada que ofrezco, el tamaño de la lista se conoce en avanzado y, por lo tanto, podría haber usado una matriz. Sin embargo, quiero ofrecer a cualquier clase base la posibilidad de extenderla dinámicamente y, por lo tanto, opto por una lista.

¿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 fuera 0. De todos modos, el hecho de que esto sea poco frecuente demuestra que va en contra del uso previsto de la clase.

¿Por qué está utilizando una lista si desea inicializarla con un valor fijo? Puedo entender que, por el bien del rendimiento, quieres 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:

 List = new List(100); 

Usted crea una lista cuya capacidad es 100 enteros. Esto significa que su Lista no tendrá que ‘crecer’ hasta que agregue el artículo 101º. La matriz subyacente de la lista se inicializará con una longitud de 100.

Inicializar los contenidos de una lista como esa no es realmente para lo que son 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 pares clave-valor como una tabla hash o diccionario en lugar de una lista.

Si desea inicializar la lista con N elementos de algún valor fijo:

 public List InitList(int count, T initValue) { return Enumerable.Repeat(initValue, count).ToList(); } 

Parece que hace hincapié en la necesidad de una asociación posicional con sus datos, de modo que ¿no sería más apropiado un conjunto asociativo?

 Dictionary foo = new Dictionary(); foo[2] = "string"; 

Cree una matriz con la cantidad de elementos que desee primero y luego convierta la matriz en una Lista.

 int[] fakeArray = new int[10]; List list = fakeArray.ToList(); 

Realmente depende de por qué quieres inicializarlo. No estoy seguro de que sea útil inicializarlo con una cierta cantidad de elementos vacíos o nulos. La ventaja de las listas es que pueden crecer según sea necesario.

El constructor de lista toma un parámetro de capacidad que se puede usar para llenarlo inicialmente.

 List = new List(10); 
 string [] temp = new string[] {"1","2","3"}; List temp2 = temp.ToList(); 

Puede usar Linq para inicializar inteligentemente su lista con un valor predeterminado. (Similar a la respuesta de David B. )

 var defaultStrings = (new int[10]).Select(x => "my value").ToList(); 

Avance un paso más e inicialice cada cadena con valores distintos “cadena 1”, “cadena 2”, “cadena 3”, etc.

 int x = 1; var numberedStrings = (new int[10]).Select(x => "string " + x++).ToList(); 

Un aviso sobre IList: MSDN IList Observaciones : “Las implementaciones de IList se dividen en tres categorías: de solo lectura, de tamaño fijo y de tamaño variable (…). Para la versión genérica de esta interfaz, consulte System.Collections.Generic.IList . ”

IList NO hereda de IList (pero List implementa tanto IList como IList ), pero siempre es de tamaño variable . Desde .NET 4.5, también tenemos IReadOnlyList pero AFAIK, no hay una lista genérica de tamaño fijo que sea lo que está buscando.

Esta es una muestra que utilicé para mi prueba unitaria. Creé una lista de objetos de clase. Luego usé forloop para agregar ‘X’ número de objetos que espero del servicio. De esta forma puede agregar / inicializar una lista para cualquier tamaño dado.

 public void TestMethod1() { var expected = new List(); for (int i = 0; i < 22; i++)//You add empty initialization here { var temp = new DotaViewer.Interface.DotaHero(); expected.Add(temp); } var nw = new DotaHeroCsvService(); var items = nw.GetHero(); CollectionAssert.AreEqual(expected,items); } 

Espero haber sido de ayuda para ustedes, chicos.

Un poco tarde, pero la primera solución que usted propuso me parece mucho más clara: no asigna memoria dos veces. Incluso el conscriptor de la Lista necesita recorrer la matriz para copiarla; ni siquiera sabe de antemano que solo hay elementos nulos dentro.

1. – asignar N-loop N Cost: 1 * allocate (N) + N * loop_iteration

2. – asignar N – asignar N + lazo () Costo: 2 * asignar (N) + N * iteración_altura

Sin embargo, la asignación de List puede ser más rápida debido a que List es una clase incorporada, pero C # se comstack de manera j …