Inicializadores de objeto y de colección (Guía de programación de C#)Object and Collection Initializers (C# Programming Guide)

Los inicializadores de objeto permiten asignar valores a cualquier campo o propiedad accesible de un objeto en el momento de su creación sin tener que invocar un constructor seguido de líneas de instrucciones de asignación.Object initializers let you assign values to any accessible fields or properties of an object at creation time without having to invoke a constructor followed by lines of assignment statements. La sintaxis de inicializador de objetos permite especificar argumentos para un constructor u omitir los argumentos (y la sintaxis de paréntesis).The object initializer syntax enables you to specify arguments for a constructor or omit the arguments (and parentheses syntax). En el ejemplo siguiente se muestra cómo usar un inicializador de objeto con un tipo con nombre, Cat, y cómo invocar el constructor predeterminado.The following example shows how to use an object initializer with a named type, Cat and how to invoke the default constructor. Tenga en cuenta el uso de propiedades implementadas automáticamente en la clase Cat.Note the use of auto-implemented properties in the Cat class. Para obtener más información, vea Propiedades implementadas automáticamente.For more information, see Auto-Implemented Properties.

class Cat
{
    // Auto-implemented properties.
    public int Age { get; set; }
    public string Name { get; set; }
}
Cat cat = new Cat { Age = 10, Name = "Fluffy" };

La sintaxis de los inicializadores de objeto le permite crear una instancia, y después asigna el objeto recién creado, con las propiedades asignadas, a la variable de la asignación.The object initializers syntax allows you to create an instance, and after that it assigns the newly created object, with its assigned properties, to the variable in the assignment.

Inicializadores de objeto con tipos anónimosObject Initializers with anonymous types

Aunque los inicializadores de objeto se pueden usar en cualquier contexto, resultan especialmente útiles en las expresiones de consulta LINQLINQ.Although object initializers can be used in any context, they are especially useful in LINQLINQ query expressions. Las expresiones de consulta usan con frecuencia tipos anónimos, que solo se pueden inicializar con un inicializador de objeto, como se muestra en la siguiente declaración.Query expressions make frequent use of anonymous types, which can only be initialized by using an object initializer, as shown in the following declaration.

var pet = new { Age = 10, Name = "Fluffy" };  

Los tipos anónimos permiten a la cláusula select de una expresión de consulta LINQLINQ transformar objetos de la secuencia original en objetos cuyo valor y forma pueden ser distintos de los originales.Anonymous types enable the select clause in a LINQLINQ query expression to transform objects of the original sequence into objects whose value and shape may differ from the original. Esto resulta útil si desea almacenar solo una parte de la información de cada objeto en una secuencia.This is useful if you want to store only a part of the information from each object in a sequence. En el ejemplo siguiente, suponga que un objeto del producto (p) contiene numerosos campos y métodos y que solo le interesa crear una secuencia de objetos que contenga el nombre del producto y el precio por unidad.In the following example, assume that a product object (p) contains many fields and methods, and that you are only interested in creating a sequence of objects that contain the product name and the unit price.

var productInfos =
    from p in products
    select new { p.ProductName, p.UnitPrice };

Al ejecutarse esta consulta, la variable productInfos incluirá una secuencia de objetos a la que se puede tener acceso en una instrucción foreach, como se muestra en este ejemplo:When this query is executed, the productInfos variable will contain a sequence of objects that can be accessed in a foreach statement as shown in this example:

foreach(var p in productInfos){...}  

Cada uno de los objetos del nuevo tipo anónimo tiene dos propiedades públicas que reciben los mismos nombres que las propiedades o campos del objeto original.Each object in the new anonymous type has two public properties which receive the same names as the properties or fields in the original object. También puede cambiar el nombre de un campo al crear un tipo anónimo; en el ejemplo siguiente se cambia el nombre del campo UnitPrice a Price.You can also rename a field when you are creating an anonymous type; the following example renames the UnitPrice field to Price.

select new {p.ProductName, Price = p.UnitPrice};  

Inicializadores de objeto con tipos que aceptan valores NULLObject initializers with nullable types

Es un error en tiempo de compilación usar un inicializador de objeto con un struct que acepta valores NULL.It is a compile-time error to use an object initializer with a nullable struct.

Inicializadores de colecciónCollection initializers

Los inicializadores de colección le permiten especificar uno o varios inicializadores de elemento al inicializar un tipo de colección que implementa IEnumerable y tiene Add con la firma apropiada como un método de instancia o un método de extensión.Collection initializers let you specify one or more element initializers when you initialize a collection type that implements IEnumerable and has Add with the appropriate signature as an instance method or an extension method. Los inicializadores de elemento pueden ser un valor simple, una expresión o un inicializador de objeto.The element initializers can be a simple value, an expression or an object initializer. Si se usa un inicializador de colección, no es necesario especificar varias llamadas al método Add de la clase en el código fuente; el compilador agrega las llamadas.By using a collection initializer you do not have to specify multiple calls to the Add method of the class in your source code; the compiler adds the calls.

En los ejemplos siguientes se muestran dos inicializadores de colección simples:The following examples shows two simple collection initializers:

List<int> digits = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };  
List<int> digits2 = new List<int> { 0 + 1, 12 % 3, MakeInt() };  

El inicializador de colección siguiente usa inicializadores de objeto para inicializar los objetos de la clase Cat definida en un ejemplo anterior.The following collection initializer uses object initializers to initialize objects of the Cat class defined in a previous example. Observe que los inicializadores de objeto individuales se escriben entre llaves y se separan por comas.Note that the individual object initializers are enclosed in braces and separated by commas.

List<Cat> cats = new List<Cat>
{
    new Cat(){ Name = "Sylvester", Age=8 },
    new Cat(){ Name = "Whiskers", Age=2 },
    new Cat(){ Name = "Sasha", Age=14 }
};

Puede especificar null como elemento de un inicializador de colección si el método Add de la colección lo permite.You can specify null as an element in a collection initializer if the collection's Add method allows it.

List<Cat> moreCats = new List<Cat>
{
    new Cat(){ Name = "Furrytail", Age=5 },
    new Cat(){ Name = "Peaches", Age=4 },
    null
};

Puede especificar elementos indexados si la colección admite la indexación.You can specify indexed elements if the collection supports indexing.

var numbers = new Dictionary<int, string> {   
    [7] = "seven",   
    [9] = "nine",   
    [13] = "thirteen"   
};  

EjemplosExamples

En el ejemplo siguiente se combinan los conceptos de inicializadores de objeto y colección.The following example combines the concepts of object and collection initializers.

// The following code consolidates examples from the topic.
class ObjInitializers
{
    class Cat
    {
        // Auto-implemented properties.
        public int Age { get; set; }
        public string Name { get; set; }
    }

    static void Main()
    {
        Cat cat = new Cat { Age = 10, Name = "Fluffy" };

        List<Cat> cats = new List<Cat>
        {
            new Cat(){ Name = "Sylvester", Age=8 },
            new Cat(){ Name = "Whiskers", Age=2 },
            new Cat(){ Name = "Sasha", Age=14 }
        };

        List<Cat> moreCats = new List<Cat>
        {
            new Cat(){ Name = "Furrytail", Age=5 },
            new Cat(){ Name = "Peaches", Age=4 },
            null
        };

        // Display results.
        System.Console.WriteLine(cat.Name);

        foreach (Cat c in cats)
            System.Console.WriteLine(c.Name);

        foreach (Cat c in moreCats)
            if (c != null)
                System.Console.WriteLine(c.Name);
            else
                System.Console.WriteLine("List element has null value.");
    }
    // Output:
    //Fluffy
    //Sylvester
    //Whiskers
    //Sasha
    //Furrytail
    //Peaches
    //List element has null value.
}

Como se muestra en el ejemplo siguiente, un objeto que implementa IEnumerable y que contiene un método Add con varios parámetros permite inicializadores de colección con varios elementos por cada elemento de la lista correspondiente a la firma del método Add.Shown in the following example, an object which implements IEnumerable containing an Add method with multiple parameters allows for collection initializers with multiple elements per item in the list corresponding to the signature of the Add method.

using System;
using System.Collections;
using System.Collections.Generic;

namespace ExampleProject
{
    class FormattedAddresses : IEnumerable<string>
    {
        private List<string> internalList = new List<string>();
        public IEnumerator<string> GetEnumerator() => internalList.GetEnumerator();

        IEnumerator IEnumerable.GetEnumerator() => internalList.GetEnumerator();

        public void Add(string firstname, string lastname, string street, string city, string state, string zipcode) => internalList.Add(
                $@"{firstname} {lastname}
{street}
{city}, {state} {zipcode}"
            );
    }

    class Program
    {
        static void Main(string[] args)
        {
            FormattedAddresses addresses = new FormattedAddresses()
            {
                {"John", "Doe", "123 Street", "Topeka", "KS", "00000" },
                {"Jane", "Smith", "456 Street", "Topeka", "KS", "00000" }
            };

            Console.WriteLine("Address Entries:");

            foreach(string addressEntry in addresses)
            {
                Console.WriteLine("\r\n" + addressEntry);
            }
        }

        /*
         * Prints:
         
            Address Entries:

            John Doe
            123 Street
            Topeka, KS 00000

            Jane Smith
            456 Street
            Topeka, KS 00000
         */
    }
}

Los métodos Add pueden usar la palabra clave params para tomar un número variable de argumentos, como se muestra en el ejemplo siguiente.Add methods can use the params keyword to take a variable number of arguments as shown in the following example. En este ejemplo se muestra la implementación personalizada de un indexador también para inicializar una colección mediante índices.This example demonstrates the custom implementation of an indexer as well to initialize a collection using indexes.

using System;
using System.Collections;
using System.Collections.Generic;

namespace ExampleProject
{
    class RudimentaryMultiValuedDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, List<TValue>>>
    {
        private Dictionary<TKey, List<TValue>> internalDictionary = new Dictionary<TKey, List<TValue>>();

        public IEnumerator<KeyValuePair<TKey, List<TValue>>> GetEnumerator() => internalDictionary.GetEnumerator();

        IEnumerator IEnumerable.GetEnumerator() => internalDictionary.GetEnumerator();

        public List<TValue> this[TKey key]
        {
            get => internalDictionary[key];
            set => Add(key, value);
        }

        public void Add(TKey key, params TValue[] values) => Add(key, (IEnumerable<TValue>)values);

        public void Add(TKey key, IEnumerable<TValue> values)
        {
            if (!internalDictionary.TryGetValue(key, out List<TValue> storedValues))
                internalDictionary.Add(key, storedValues = new List<TValue>());

            storedValues.AddRange(values);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            RudimentaryMultiValuedDictionary<string, string> rudimentaryMultiValuedDictionary1
                = new RudimentaryMultiValuedDictionary<string, string>()
                {
                    {"Group1", "Bob", "John", "Mary" },
                    {"Group2", "Eric", "Emily", "Debbie", "Jesse" }
                };
            RudimentaryMultiValuedDictionary<string, string> rudimentaryMultiValuedDictionary2
                = new RudimentaryMultiValuedDictionary<string, string>()
                {
                    ["Group1"] = new List<string>() { "Bob", "John", "Mary" },
                    ["Group2"] = new List<string>() { "Eric", "Emily", "Debbie", "Jesse" }
                };

            Console.WriteLine("Using first multi-valued dictionary created with a collection initializer:");

            foreach(KeyValuePair<string, List<string>> group in rudimentaryMultiValuedDictionary1)
            {
                Console.WriteLine($"\r\nMembers of group {group.Key}: ");

                foreach(string member in group.Value)
                {
                    Console.WriteLine(member);
                }
            }

            Console.WriteLine("\r\nUsing second multi-valued dictionary created with a collection initializer using indexing:");

            foreach (KeyValuePair<string, List<string>> group in rudimentaryMultiValuedDictionary2)
            {
                Console.WriteLine($"\r\nMembers of group {group.Key}: ");

                foreach (string member in group.Value)
                {
                    Console.WriteLine(member);
                }
            }
        }

        /*
         * Prints:
         
            Using first multi-valued dictionary created with a collection initializer:

            Members of group Group1:
            Bob
            John
            Mary

            Members of group Group2:
            Eric
            Emily
            Debbie
            Jesse

            Using second multi-valued dictionary created with a collection initializer using indexing:

            Members of group Group1:
            Bob
            John
            Mary

            Members of group Group2:
            Eric
            Emily
            Debbie
            Jesse
         */
    }
}

Vea tambiénSee Also

Guía de programación de C#C# Programming Guide
Expresiones de consulta LINQLINQ Query Expressions
Tipos anónimosAnonymous Types