3 out of 9 rated this helpful Rate this topic

Object and Collection Initializers (C# Programming Guide)

Updated: October 2010

Object initializers let you assign values to any accessible fields or properties of an object at creation time without having to explicitly invoke a constructor. The following example shows how to use an object initializer with a named type, Cat. Note the use of auto-implemented properties in the Cat class. For more information, see Auto-Implemented Properties (C# Programming Guide).


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



Cat cat = new Cat { Age = 10, Name = "Fluffy" };


Although object initializers can be used in any context, they are especially useful in LINQ query expressions. 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" };

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. This is useful if you want to store only a part of the information from each object in a sequence. 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 };


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

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

It is a compile-time error to use a collection initializer with a nullable struct.

Collection initializers let you specify one or more element intializers when you initialize a collection class that implements IEnumerable. The element initializers can be a simple value, an expression or an object initializer. 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.

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() };

The following collection initializer uses object initializers to initialize objects of the Cat class defined in a previous example. 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 }
};


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



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


Date

History

Reason

October 2010

Added an example of an anonymous-type declaration that is not part of a LINQ query. Added a link to a topic that has more information about anonymous types.

Customer feedback.

Did you find this helpful?
(2000 characters remaining)
Community Content Add
Annotations FAQ
Dictionary initializers
No reference is made in this document to dictionary initializers, and in particular the requirements for custom types to allow this.$0 $0 Edit: see http://msdn.microsoft.com/en-us/library/bb531208.aspx
Magic methods probably make sense here
Personally, I'm not sure why the type even has to be IEnumerable. Perhaps the C# language design team included that as a basic sanity check.

Requiring ICollection could have worked, except that doing so would imply the use of the ICollection.Add() method. For types implementing ICollection and ICollection<T>, that either means potentially boxing value types, or complicating the specification to deal with sometimes using ICollection and sometimes using ICollection<T>.

Also, even if one accepts that, going through ICollection or ICollection<T> means using only one Add() method. As things stand today, normal overload resolution occurs on the items being added. So if you do happen to have an IEnumerable type that has overloaded Add() methods that accept a variety of types, you can include any of those types in the initializer and still be sure that the correct Add() method will be used for that type.

I agree that from a general philosophical point of view, keying off of some magic method in a type for the feature seems a little weak, especially for a strongly-static language like C#. But note that this similar to the approach used for LINQ, where the main thing that matters are the presence of the requisite Where(), Select(), OrderBy(), etc. methods so that after the compiler has mechanically translated the expression to plain method calls, all that happens after that is normal compilation that doesn't need to know anything about the "fancy" feature.

Same thing here. All the compiler has to do is do a quick check on the constructed type for the IEnumerable interface, and then mechanically convert the initializer to literal Add() calls, which are then compiled normally without having to treat them differently from user-written code (such as providing a temp variable of the appropriate interface type, and calling the interface's Add() method instead).

So at least this isn't some single anomaly in the language.  :)
Collection Initializers kind of dirty
There is no 'Add' method in IEnumerable, so, why not request/require an implementation of ICollection? Currently there just should be a method named Add, kind of dirty i think.
Advertisement