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 commentAnonymous
February 22, 2006
Your blog is really very interesting.Anonymous
April 19, 2006
The comment has been removedAnonymous
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 readableAnonymous
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 answerAnonymous
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&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 and hereI do not agree. Go to http://www.hotelsstore.info/liar_France/ocellus_Nord%20Pas%20de%20Calais/explicatory_Lille_1.htmlAnonymous
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.aspxAnonymous
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 and hereI do not agree. Go to http://www.greatjobz.info/bronchi_Italy/invulnerability_Toscana/dobbin_Florence_1.htmlAnonymous
September 11, 2007
PingBack from http://www.kintespace.com/rasxlog/?p=738Anonymous
November 15, 2007
How not to use ASP.AJAX - Pt 2Anonymous
November 20, 2007
Noch mehr Schreibarbeit spart man zusätzlich mit den Collection Initializers, die so ähnlich wie dieAnonymous
November 21, 2007
In my last post I had discussed about anonymous methods. I had used the following code snippet to showAnonymous
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 removedAnonymous
December 12, 2008
The comment has been removedAnonymous
September 07, 2010
I've been using the heck outta this feature. almost too much ;)