Share via


C# 3.0: I love object and collection initializers

This is the my fourth post in the series of posts I am making on C#3.0. See the previous posts here, here and here

Object and collection initializers are new features in C#3.0 which is syntactic sugar over how you allocate and initialize objects and collections.

Object Initializers

Lets consider a class

 class Customer{    public string name;    public string address;    int age;    public int Age { get { return age; } set { age = value; } }}

if I wanted to create a object of the type customer and fill up the public variables and properties then in C#2.0 I need to do something like

 Customer customer = new Customer();customer.name = "Abhinaba Basu";customer.address = "1835 73rd Ave NE, Medina, WA 98039";customer.Age = 99;

With the new object initializer syntax it possible to do all of the above in one statement as in

 var cust = new Customer{name = "Abhinaba Basu", 
                 address = "1835 73rd Ave NE, Medina, WA 98039",
                 Age = 99 };

This not only reduces lines of code but increases flexibility a lot. So no more being forced to write 5 overloads of a contructor that just accepts these variables and assigns them to fields.This syntax works for both public fields and properties.

In case the class contains other classes as fields then the same statement can also initialize the contained class (see code below in bold).

 class Phone{    public int countryCode;    public int areaCode;    public int number;}class Customer{    public string name;    public string address;    publicPhone phone; }static void Main(string[] args){    var cust = new Customer{name = "Abhinaba Basu", 
                     address = "1835 73rd Ave NE, Medina, WA 98039",                      phone =  newPhone  {countryCode = 1, areaCode = 425, <br>                                        number = 9999999}}; }

This piece of code is equivalent to the following C#2.0 code

 Customer customer = new Customer();customer.name = "Abhinaba Basu";customer.address = "1835 73rd Ave NE, Medina, WA 98039";Phone __phone = new Phone();__phone.countryCode = 1;__phone.areaCode = 425;__phone.number = 9999999;customer.phone = __phone;

Collection Initializers

Collection initializer is a natural extension to object initializer. It consists of a list of initilializer for each of the elements in a collection seperated by comma and encosed in {}. For a simple List<int> it is as follows

 List<int> digits = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

For the Customer and Phone number class discussed above the collection initializer will look like

 List<Customer> custList = new List<Customer> {    new Customer {        name = "Samrat", address = "NJ, USA",         phone = new Phone {countryCode = 91, areaCode = 999, number = 8888888}    },    new Customer {        name = "Kaushik", address = "Behala, Kolkata",         phone = new Phone {countryCode = 91, areaCode = 33, number = 3333333}    },    new Customer {        name = "Rahul", address = "Kerala",         phone = new Phone {countryCode = 91, areaCode = 00, number = 4444}    }};

Just trying to write the above piece of code in C#2.0 syntax shows how cool this new feature is.

Why I love this

This feature reduce typing a lot and will go a long way in helping reduce carpal tunnel syndrome :^)

Moreover, it is very intuitive, so much so that people will start using this even without figuring out that this was not present before and they were required to allocate the collection and then individually allocate and add each item to the collection. Just after using it for a couple of days I am badly missing it in C#2.0. I just can't figure out why this was not considered for 2.0. I can guess why but I'll still complain :)

Comments

  • Anonymous
    September 17, 2005
    Ok, now this I like! Forget lambda functions, continuation, and all that other jazz. This is a feature that will save keystrokes, that is intuitive, and that instantly makes sense to all C# developers!

    Let's see more stuff like this that everyone can benefit from!

  • Anonymous
    September 17, 2005
    This looks cool, though is it just limited to public fields? Setting properties would be nice.

    Does this only work if there is no default constructor for an object?

  • Anonymous
    September 17, 2005
    This is a really nice addition!

    It would be nice to get a CTP preview release add-in for VS2005 for some of these C# 3.0 features. It will be too hard to wait 2-3 years until the next release!

  • Anonymous
    September 17, 2005
    The collection initializer is nice, but you can do something similar in C# 2.0 with only a little bit more work. For example, your sample would look like:

    List<int> digits = new List<int> (
    new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 });

  • Anonymous
    September 17, 2005
    Am I correct in assuming that any "readonly" fields will not be accepted in the initalizer, as I guess it's just syntactic sugar? This means you'll still need the different constructors for types where it has to be immutable, for example simple struct containers, where this would otherwise be a very nice syntax.

  • Anonymous
    September 17, 2005
    What happens when Customer does not have a default constructor. Does it allow something like this?

    var cust = new Customer( init1, init2 ) // <- Non-default constructor
    {name = "Abhinaba Basu", address = "1835 73rd Ave NE, Medina, WA 98039", Age = 99 };

  • Anonymous
    September 17, 2005
    The answer to each of the questions above

    Q. Are properties supported (Jeff)
    A. Yes they are. To illustrate this I specifically added Age as a property in Customer class

    Q. Does this only work if there is no default constructor for an object (jeff)
    A. This has nothing to do with presense of ctor. Lets see the following example where there is a ctor and you invoke both the ctor as well as use the initializer syntax

    class Item
    {
    private int m_itemId;
    private string m_itemName;

    public Item(int itemId, string itemName)
    {
    m_itemId = itemId;
    m_itemName = itemName;
    }

    public string description;
    }
    Item item = new Item (12, "Football") { description = "Size 4 footbal" } ;

    Q. C#2.0 (or 1.0) already had some thing like
    List<int> digits = new List<int> (
    new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }); (victor)
    A. Well yes, this is ok with value types. For reference types you can allocate the objects and then add them in one statement, either as above or using List<>.AddRange. But you had to manage the intermediate variables to store inidividual items. There was no way to do the whole thing in one statement. So effectively with this new syntax value and reference type collection initialization is becoming the same.

    Q.Does it work with Readonly fields (CN)
    A. You are right this is just syntactic sugar and hence will not work with readonly fields.

    Q. What happens with non-default ctor (zz)
    A. You are absolutely right it works just as you thought. See the sample in this comment

  • Anonymous
    February 22, 2006
    Your blog is really very interesting.

  • Anonymous
    April 19, 2006
    The comment has been removed

  • Anonymous
    April 20, 2006
    For those who has worked with VB will find this feature still incomplete. If we are talking about C# 3.0 you should seriously consider implementing "With" keyword as supported in VB. In that case C# 3.0 code may look like following:

    With (customer = new Customer()){
        .name = "Abhinaba Basu";
        .address = "1835 73rd Ave NE, Medina, WA 98039";
        .Age = 99;
    }

    IMHO, the feature you described does very little as far as readability has cocerned, beside that it only supported in constructor. However if you implement "With" keyword, it will have more than one advantages:
    1. You can use it anywhere (not limited to constructor)
    2. CLR/JIT can omptimize performance
    3. More readable

  • Anonymous
    April 21, 2006
    The collection initializer is not working with Dictionary<TKey, TValue>, any chance for a fix?

  • Anonymous
    April 21, 2006
    Kazi, can you post any code snippet of what exactly is not working? I'll try to get you an answer

  • Anonymous
    April 22, 2006
    A simple sample for generic Dictionary objects trying to initialize with collection initializers (compiler error messages inculded):

    // Error: Cannot implicitly convert type 'string' to 'System.Collections.Generic.KeyValuePair<string,int>'
    var dict1 = new Dictionary<string, int>() {"one", 1};

    // Error: No overload for method 'Add' takes '1' arguments
    var dict2 = new Dictionary<string, int>() {new KeyValuePair<string, int>("one", 1)};

  • Anonymous
    August 23, 2006
    In my last post&amp;nbsp;I had discussed about anonymous methods.
    I had used the following code snippet...

  • Anonymous
    September 26, 2006
    I got here looking for information similar to CNs... and am dissappointed.  Are there any plans to make "immutable" objects less painful?  

    Right now there is no easy way to say "Copy X but with changed properties X.A and X.B".  Being able to designate a field or property as "Initializable" instead of "ReadOnly" to allow immutable functionality would make things less painful.

    Imagine being able to say

    myFont = new Font(myFont){Size = 8}

    instead of

    myFont = new Font(
            myFont.FontFamily,
            8,
            myFont.Style,
            GraphicsUnit.Point,
            myFont.GdiCharSet,
            myFont.GdiVerticalFont
    );

    Theoritically one can do similar functionality with tons of heavily overloaded codegenned constructors, but even that falls apart if you have multiple properties with the same type.

  • Anonymous
    October 06, 2006
    PingBack from http://mdavey.wordpress.com/2006/10/06/orcas-sept-ctp/

  • Anonymous
    November 21, 2006
    This is the my fourth post in the series of posts I am making on C#3.0. See the previous posts here, here&nbsp;and hereI do not agree. Go to http://www.hotelsstore.info/liar_France/ocellus_Nord%20Pas%20de%20Calais/explicatory_Lille_1.html

  • Anonymous
    January 10, 2007
    I have posted an article on why collection initializers are a terrible idea at http://commongenius.com/articles/archive/2006/12/07/Collection-Initializers-and-Duck-Typing.aspx

  • Anonymous
    February 22, 2007
    For tabs, you can do thisint[] tab = { 1, 2, 3};

  • Anonymous
    March 21, 2007
    This is the my fourth post in the series of posts I am making on C#3.0. See the previous posts here, here&nbsp;and hereI do not agree. Go to http://www.greatjobz.info/bronchi_Italy/invulnerability_Toscana/dobbin_Florence_1.html

  • Anonymous
    September 11, 2007
    PingBack from http://www.kintespace.com/rasxlog/?p=738

  • Anonymous
    November 15, 2007
    How not to use ASP.AJAX - Pt 2

  • Anonymous
    November 20, 2007
    Noch mehr Schreibarbeit spart man zusätzlich mit den Collection Initializers, die so ähnlich wie die

  • Anonymous
    November 21, 2007
    In my last post I had discussed about anonymous methods. I had used the following code snippet to show

  • Anonymous
    May 12, 2008
    Kazi, Try this: static void Main(string[] args) { Dictionary<string, int> MyMap = new Dictionary<string, int>() { { "one", 1 }, { "two", 2 }};   Console.WriteLine("one is {0}", MyMap["one"].ToString()); Console.WriteLine("two is {0}", MyMap["two"].ToString()); }

  • Anonymous
    June 20, 2008
    Thank for putting it so nicely.

  • Anonymous
    December 12, 2008
    The comment has been removed

  • Anonymous
    December 12, 2008
    The comment has been removed

  • Anonymous
    September 07, 2010
    I've been using the heck outta this feature. almost too much ;)