Initialiseurs d’objet et de collection (Guide de programmation C#)Object and Collection Initializers (C# Programming Guide)

C# vous permet d’instancier un objet ou une collection et d’effectuer des affectations de membres dans une seule instruction.C# lets you instantiate an object or collection and perform member assignments in a single statement.

Initialiseurs d’objetObject initializers

Les initialiseurs d'objet vous permettent d'affecter des valeurs aux champs ou propriétés accessibles d'un objet, au moment de sa création, sans devoir appeler un constructeur suivi de ses lignes d'instructions d'assignation.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 syntaxe de l'initialiseur de l'objet vous permet de spécifier les arguments d'un constructeur ou de les omettre (et la syntaxe de parenthèses).The object initializer syntax enables you to specify arguments for a constructor or omit the arguments (and parentheses syntax). L'exemple suivant montre comment utiliser l'initialiseur de l'objet de type nommé, Cat, et comment appeler le constructeur sans paramètre.The following example shows how to use an object initializer with a named type, Cat and how to invoke the parameterless constructor. Notez l'utilisation de propriétés implémentées automatiquement dans la classe Cat.Note the use of auto-implemented properties in the Cat class. Pour plus d’informations, consultez Propriétés implémentées automatiquement.For more information, see Auto-Implemented Properties.

public class Cat
{
    // Auto-implemented properties.
    public int Age { get; set; }
    public string Name { get; set; }

    public Cat()
    {
    }

    public Cat(string name)
    {
        this.Name = name;
    }
}
Cat cat = new Cat { Age = 10, Name = "Fluffy" };
Cat sameCat = new Cat("Fluffy"){ Age = 10 };

La syntaxe des initialiseurs d’objet vous permet de créer une instance qui assigne l’objet nouvellement créé, avec ses propriétés, à la variable dans l’assignation.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.

À compter de C# 6, les initialiseurs d’objet peuvent, en plus d’affecter des champs et des propriétés, définir des indexeurs.Starting with C# 6, object initializers can set indexers, in addition to assigning fields and properties. Prenez l’exemple de cette classe Matrix de base :Consider this basic Matrix class:

public class Matrix
{
    private double[,] storage = new double[3, 3];

    public double this[int row, int column]
    {
        // The embedded array will throw out of range exceptions as appropriate.
        get { return storage[row, column]; }
        set { storage[row, column] = value; }
    }
}

Vous pouvez initialiser la matrice identity avec le code suivant :You could initialize the identity matrix with the following code:

var identity = new Matrix
{
    [0, 0] = 1.0,
    [0, 1] = 0.0,
    [0, 2] = 0.0,

    [1, 0] = 0.0,
    [1, 1] = 1.0,
    [1, 2] = 0.0,

    [2, 0] = 0.0,
    [2, 1] = 0.0,
    [2, 2] = 1.0,
};

Tout indexeur accessible qui contient un setter accessible peut être utilisé comme l’une des expressions d’un initialiseur d’objet, indépendamment du nombre ou des types d’arguments.Any accessible indexer that contains an accessible setter can be used as one of the expressions in an object initializer, regardless of the number or types of arguments. Les arguments d’index forment le côté gauche de l’affectation, et la valeur le côté droit de l’expression.The index arguments form the left side of the assignment, and the value is the right side of the expression. Par exemple, les éléments suivants sont tous valides si IndexersExample a les indexeurs appropriés :For example, these are all valid if IndexersExample has the appropriate indexers:

var thing = new IndexersExample {
    name = "object one",
    [1] = '1',
    [2] = '4',
    [3] = '9',
    Size = Math.PI,
    ['C',4] = "Middle C"
}

Pour le code précédent à compiler, le type IndexersExample doit avoir les membres suivants :For the preceding code to compile, the IndexersExample type must have the following members:

public string name;
public double Size { set { ... }; }
public char this[int i] { set { ... }; }
public string this[char c, int i] {  set { ... }; }

Initialiseurs d'objet avec des types anonymesObject Initializers with anonymous types

Bien que les initialiseurs d’objets puissent être utilisés dans n’importe quel contexte, ils sont particulièrement utiles dans les expressions de requête LINQ.Although object initializers can be used in any context, they are especially useful in LINQ query expressions. Les expressions de requête utilisent souvent des types anonymes, qui peuvent uniquement être initialisés à l’aide d’un initialiseur d’objet, comme indiqué dans la déclaration suivante.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" };  

Les types anonymes activent la clause select dans une expression de requête LINQ pour transformer les objets de la séquence d’origine en objets dont la valeur et la forme peuvent différer de l’original.Anonymous types enable the select clause in a LINQ query expression to transform objects of the original sequence into objects whose value and shape may differ from the original. Cela s'avère utile si vous souhaitez stocker uniquement une partie des informations de chaque objet d'une séquence.This is useful if you want to store only a part of the information from each object in a sequence. Dans l'exemple suivant, supposons qu'un objet de produit (p) contient de nombreux champs et méthodes et que vous souhaitez uniquement créer une séquence d'objets qui contiennent le nom de produit et le prix unitaire.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 };

Lorsque cette requête est exécutée, la variable productInfos contient une séquence d'objets qui sont accessibles dans une instruction foreach comme indiqué dans cet exemple :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){...}  

Chaque objet dans le nouveau type anonyme a deux propriétés publiques qui reçoivent les mêmes noms que les propriétés ou champs de l’objet d’origine.Each object in the new anonymous type has two public properties that receive the same names as the properties or fields in the original object. Vous pouvez également renommer un champ lorsque vous créez un type anonyme. L'exemple suivant renomme le champ UnitPrice en 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};  

Initialiseurs de collectionCollection initializers

Les initialiseurs de collection vous permettent de spécifier un ou plusieurs initialiseurs d’élément quand vous initialisez un type de collection qui implémente IEnumerable et qui utilise Add comme méthode d’instance ou méthode d’extension avec la signature appropriée.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. Les initialiseurs d’élément peuvent être une valeur simple, une expression ou un initialiseur d’objet.The element initializers can be a simple value, an expression, or an object initializer. En utilisant un initialiseur de collection, il n’est pas nécessaire de spécifier plusieurs appels ; le compilateur les ajoute automatiquement.By using a collection initializer, you do not have to specify multiple calls; the compiler adds the calls automatically.

L’exemple suivant montre deux initialiseurs de collection simples :The following example 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() };  

L'initialiseur de collection suivant utilise des initialiseurs d'objets pour initialiser les objets de la classe Cat définis dans un exemple précédent.The following collection initializer uses object initializers to initialize objects of the Cat class defined in a previous example. Notez que les initialiseurs d'objets individuels sont placés entre accolades et séparés par une virgule.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 }
};

Vous pouvez spécifier Null comme élément dans un initialiseur de collection si la méthode Add de la collection l’autorise.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
};

Vous pouvez spécifier des éléments indexés si la collection prend en charge l’indexation en lecture/écriture.You can specify indexed elements if the collection supports read / write indexing.

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

L’exemple précédent génère du code qui appelle Item[TKey] pour définir les valeurs.The preceding sample generates code that calls the Item[TKey] to set the values. Avant C# le 6, vous pouviez initialiser des dictionnaires et d’autres conteneurs associatifs à l’aide de la syntaxe suivante.Before C# 6, you could initialize dictionaries and other associative containers using the following syntax. Notez que la syntaxe de l’indexeur, avec des parenthèses et une affectation, est remplacée par un objet avec plusieurs valeurs :Notice that instead of indexer syntax, with parentheses and an assignment, it uses an object with multiple values:

var moreNumbers = new Dictionary<int, string>
{
    {19, "nineteen" },
    {23, "twenty-three" },
    {42, "forty-two" }
};

Cet exemple d’initialiseur appelle Add(TKey, TValue) pour ajouter les trois éléments dans le dictionnaire.This initializer example calls Add(TKey, TValue) to add the three items into the dictionary. Ces deux manières d’initialiser les collections associatives ont un comportement légèrement différent en raison des appels de méthode générés par le compilateur.These two different ways to initialize associative collections have slightly different behavior because of the method calls the compiler generates. Les deux variantes fonctionnent avec la classe Dictionary.Both variants work with the Dictionary class. D’autres types peuvent uniquement prendre en charge l’une ou l’autre en fonction de leur API publique.Other types may only support one or the other based on their public API.

ExemplesExamples

L’exemple suivant combine les concepts d’initialiseurs d’objet et de collection.The following example combines the concepts of object and collection initializers.

public class InitializationSample
{
    public class Cat
    {
        // Auto-implemented properties.
        public int Age { get; set; }
        public string Name { get; set; }

        public Cat() { }

        public Cat(string name)
        {
            Name = name;
        }
    }

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

        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.
}

L’exemple suivant montre un objet qui implémente IEnumerable et qui contient une méthode Add avec plusieurs paramètres. Il utilise un initialiseur de collection avec plusieurs éléments dans la liste correspondant à la signature de la méthode Add.The following example shows an object that implements IEnumerable and contains an Add method with multiple parameters, It uses a collection initializer with multiple elements per item in the list that correspond to the signature of the Add method.

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

            System.Collections.IEnumerator System.Collections.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}"
                );
        }

        public static void Main()
        {
            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
         */
    }

Les méthodes Add peuvent utiliser le mot clé params pour sélectionner un nombre variable d’arguments, comme indiqué dans l’exemple suivant.Add methods can use the params keyword to take a variable number of arguments, as shown in the following example. Cet exemple montre également l’implémentation personnalisée d’un indexeur pour initialiser une collection à l’aide d’index.This example also demonstrates the custom implementation of an indexer to initialize a collection using indexes.

public class DictionaryExample
{ 
    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();

        System.Collections.IEnumerator System.Collections.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);
        }
    }

    public static void Main()
    {
        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" }
            };
        RudimentaryMultiValuedDictionary<string, string> rudimentaryMultiValuedDictionary3
            = new RudimentaryMultiValuedDictionary<string, string>()
            {
                {"Group1", new string []{ "Bob", "John", "Mary" } },
                { "Group2", new 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);
            }
        }
        Console.WriteLine("\r\nUsing third multi-valued dictionary created with a collection initializer using indexing:");

        foreach (KeyValuePair<string, List<string>> group in rudimentaryMultiValuedDictionary3)
        {
            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

        Using third 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
     */
}

Voir aussiSee also