Buscar..


Observaciones

El único requisito para que un objeto se inicialice utilizando este azúcar sintáctico es que el tipo implemente System.Collections.IEnumerable y el método Add . Aunque lo llamamos un inicializador de colección, el objeto no tiene que ser una colección.

Inicializadores de colección

Inicializar un tipo de colección con valores:

var stringList = new List<string>
{
    "foo",
    "bar",
};

Los inicializadores de colección son azúcar sintáctica para llamadas Add() . El código anterior es equivalente a:

var temp = new List<string>();
temp.Add("foo");
temp.Add("bar");
var stringList = temp;

Tenga en cuenta que la inicialización se realiza de forma atómica utilizando una variable temporal, para evitar las condiciones de carrera.

Para los tipos que ofrecen múltiples parámetros en su método Add() , incluya los argumentos separados por comas entre llaves:

var numberDictionary = new Dictionary<int, string>
{
    { 1, "One" },
    { 2, "Two" },
};

Esto es equivalente a:

var temp = new Dictionary<int, string>();
temp.Add(1, "One");
temp.Add(2, "Two");
var numberDictionarynumberDictionary = temp;

Inicializadores de índice C # 6

A partir de C # 6, las colecciones con indizadores se pueden inicializar especificando el índice a asignar entre corchetes, seguido de un signo igual, seguido del valor a asignar.

Inicialización del diccionario

Un ejemplo de esta sintaxis usando un Diccionario:

var dict = new Dictionary<string, int>
{
    ["key1"] = 1,
    ["key2"] = 50
};

Esto es equivalente a:

var dict = new Dictionary<string, int>();
dict["key1"] = 1;
dict["key2"] = 50

La sintaxis de inicialización de colección para hacer esto antes de C # 6 era:

var dict = new Dictionary<string, int>
{
    { "key1", 1 },
    { "key2", 50 }
};

Que correspondería a:

var dict = new Dictionary<string, int>();
dict.Add("key1", 1);
dict.Add("key2", 50);

Por lo tanto, existe una diferencia significativa en la funcionalidad, ya que la nueva sintaxis utiliza el indexador del objeto inicializado para asignar valores en lugar de usar su método Add() . Esto significa que la nueva sintaxis solo requiere un indexador disponible públicamente y funciona para cualquier objeto que tenga uno.

public class IndexableClass
{
    public int this[int index]
    {
        set 
        { 
            Console.WriteLine("{0} was assigned to index {1}", value, index);
        }
    }
}

var foo = new IndexableClass
{
    [0] = 10,
    [1] = 20
}

Esto daría como resultado:

10 was assigned to index 0
20 was assigned to index 1

Colección de inicializadores en clases personalizadas.

Para hacer que una clase sea compatible con los inicializadores de colección, debe implementar la interfaz IEnumerable y tener al menos un método Add . Desde C # 6, cualquier colección que implemente IEnumerable puede extenderse con métodos personalizados de Add utilizando métodos de extensión.

class Program
{
    static void Main()
    {
        var col = new MyCollection {
            "foo",
            { "bar", 3 },
            "baz",
            123.45d,
        };
    }
}

class MyCollection : IEnumerable
{
    private IList list = new ArrayList();

    public void Add(string item)
    {
        list.Add(item)
    }

    public void Add(string item, int count)
    {
        for(int i=0;i< count;i++) {
            list.Add(item);
        }
    }

    public IEnumerator GetEnumerator()
    {
        return list.GetEnumerator();
    }
}

static class MyCollectionExtensions
{
    public static void Add(this MyCollection @this, double value) => 
        @this.Add(value.ToString());
}

Inicializadores de colección con matrices de parámetros

Puedes mezclar parámetros normales y matrices de parámetros:

public class LotteryTicket : IEnumerable{
    public int[] LuckyNumbers;
    public string UserName;

    public void Add(string userName, params int[] luckyNumbers){
        UserName = userName;
        Lottery = luckyNumbers;
    }
}

Esta sintaxis es ahora posible:

var Tickets = new List<LotteryTicket>{
    {"Mr Cool"  , 35663, 35732, 12312, 75685},
    {"Bruce"    , 26874, 66677, 24546, 36483, 46768, 24632, 24527},
    {"John Cena", 25446, 83356, 65536, 23783, 24567, 89337}
}

Usando el inicializador de colección dentro del inicializador de objeto

public class Tag
{
    public IList<string> Synonyms { get; set; }
}

Synonyms es una propiedad de tipo colección. Cuando el objeto Tag se crea utilizando la sintaxis del inicializador de objetos, los Synonyms también se pueden inicializar con la sintaxis del inicializador de colecciones:

Tag t = new Tag 
{
    Synonyms = new List<string> {"c#", "c-sharp"}
};

La propiedad de colección puede ser de solo lectura y aún así admite la sintaxis del inicializador de colección. Considere este ejemplo modificado (la propiedad Synonyms ahora tiene un setter privado):

public class Tag
{
    public Tag()
    {
        Synonyms = new List<string>();
    }
    
    public IList<string> Synonyms { get; private set; }
}

Un nuevo objeto Tag se puede crear así:

Tag t = new Tag 
{
    Synonyms = {"c#", "c-sharp"}
};

Esto funciona porque los inicializadores de la colección son solo azúcar sintética sobre las llamadas a Add() . No se está creando una lista nueva aquí, el compilador está generando llamadas a Add() en el objeto que sale.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow