Hoy me sorprendió descubrir que en C # puedo hacer:
List<int> a = new List<int> { 1, 2, 3 };
¿Por qué puedo hacer esto? ¿Qué constructor se llama? ¿Cómo puedo hacer esto con mis propias clases? Sé que esta es la forma de inicializar matrices, pero las matrices son elementos de lenguaje y las listas son objetos simples ...
c#
.net
list
initialization
Ignacio Soler García
fuente
fuente
{ { "key1", "value1"}, { "key2", "value2"} }
List<int>
es en realidad solo una matriz. Odio el equipo de C # por el hecho de que no lo nombran, loArrayList<T>
que suena tan obvio y natural.Respuestas:
Esto es parte de la sintaxis del inicializador de colección en .NET. Puede usar esta sintaxis en cualquier colección que cree siempre que:
Implementa
IEnumerable
(preferiblementeIEnumerable<T>
)Tiene un método llamado
Add(...)
Lo que sucede es que se llama al constructor predeterminado, y luego
Add(...)
se llama para cada miembro del inicializador.Por lo tanto, estos dos bloques son más o menos idénticos:
Y
Usted puede llamar a un constructor alternativo si lo desea, por ejemplo, para evitar el exceso de dimensionar el
List<T>
durante el cultivo, etc:Tenga en cuenta que el
Add()
método no necesita tomar un solo elemento, por ejemplo, elAdd()
métodoDictionary<TKey, TValue>
toma dos elementos:Es aproximadamente idéntico a:
Entonces, para agregar esto a su propia clase, todo lo que necesita hacer, como se mencionó, es implementar
IEnumerable
(nuevamente, preferiblementeIEnumerable<T>
) y crear uno o másAdd()
métodos:Luego puede usarlo como lo hacen las colecciones BCL:
(Para más información, vea el MSDN )
fuente
List<int> temp = new List<int>(); temp.Add(1); ... List<int> a = temp;
Es decir, laa
variable no se inicializa hasta que después de toda la suma que se llama. De lo contrario, sería legal hacer algo como loList<int> a = new List<int>() { a.Count, a.Count, a.Count };
que es una locura.List<int> a; a = new List<int>() { a.Count };
yList<int> a = new List<int>() { a.Count };
T x = y;
es lo mismo queT x; x = y;
, Este hecho puede conducir a algunas situaciones extrañas. Por ejemplo,int x = M(out x) + x;
es perfectamente legal porqueint x; x = M(out x) + x;
es legal.IEnumerable<T>
; el no genéricoIEnumerable
es suficiente para permitir el uso de la sintaxis de inicializador de colección.using (var x = new Something{ 1, 2 })
no eliminará el objeto siAdd
falla una de las llamadas.Se llama azúcar sintáctico .
List<T>
es la clase "simple", pero el compilador le da un tratamiento especial para facilitarle la vida.Este se llama inicializador de colección . Necesita implementar
IEnumerable<T>
yAdd
método.fuente
De acuerdo con la especificación de C # Versión 3.0 "El objeto de colección al que se aplica un inicializador de colección debe ser de un tipo que implemente System.Collections.Generic.ICollection para exactamente una T."
Sin embargo, esta información parece ser inexacta al momento de escribir esto; vea la aclaración de Eric Lippert en los comentarios a continuación.
fuente
Funciona gracias a los inicializadores de colección que básicamente requieren que la colección implemente un método Add y que hará el trabajo por usted.
fuente
¡Otra cosa interesante sobre los inicializadores de colección es que puede tener múltiples sobrecargas de
Add
método y puede llamarlos a todos en el mismo inicializador! Por ejemplo, esto funciona:Llama a las sobrecargas correctas. Además, busca solo el método con el nombre
Add
, el tipo de retorno podría ser cualquier cosa.fuente
La sintaxis tipo matriz se está convirtiendo en una serie de
Add()
llamadas.Para ver esto en un ejemplo mucho más interesante, considere el siguiente código en el que hago dos cosas interesantes que suenan primero ilegales en C #, 1) establecer una propiedad de solo lectura, 2) establecer una lista con una matriz como inicializador.
Este código funcionará perfectamente, aunque 1) MyList es de solo lectura y 2) configuro una lista con inicializador de matriz.
La razón por la que esto funciona es porque en el código que forma parte de un intializador de objetos, el compilador siempre convierte cualquier
{}
sintaxis similar en una serie deAdd()
llamadas que son perfectamente legales incluso en un campo de solo lectura.fuente