New C# "Orcas" Language Features: Automatic Properties, Object Initializers, and Collection Initializers
Last week we shipped the March CTP of our Visual Studio and .NET Framework "Orcas" release. It is available as a free download by anyone, and can be downloaded as as both a VPC (allowing you to run it in a virtual machine) as well as a standalone setup install (note: if you are running Vista you want to make sure you only use the VPC version). You can download it here.
A few weeks ago I blogged about some of the major improvements coming for ASP.NET developers with the "Orcas" release. If you haven't already read this blog post, I highly recommend reading it here. I think you'll really like the new features it covers.
In addition to all the great new framework and tool features, one of the things that I think developers (of all .NET application types) will really love about Orcas are some of the new language features and improvements that are coming to both VB and C#. These language changes are going to improve our development experience in both subtle and dramatic ways, and will really improve productivity and reduce the amount of code we need to type.
Over the next few weeks I'm going to try and blog about several of these language improvements, and show how they can be used together to produce some really powerful results.
New C# Language Feature: Automatic Properties
If you are a C# developer today, you are probably quite used to writing classes with basic properties like the code-snippet below:
private string _firstName;
private string _lastName;
private int _age;
public string FirstName {
get {
return _firstName;
}
set {
_firstName = value;
}
}
public string LastName {
get {
return _lastName;
}
set {
_lastName = value;
}
}
public int Age {
get {
return _age;
}
set {
_age = value;
}
}
}
Note about that we aren't actually adding any logic in the getters/setters of our properties - instead we just get/set the value directly to a field. This begs the question - then why not just use fields instead of properties? Well - there are a lot of downsides to exposing public fields. Two of the big problems are: 1) you can't easily databind against fields, and 2) if you expose public fields from your classes you can't later change them to properties (for example: to add validation logic to the setters) without recompiling any assemblies compiled against the old class.
The new C# compiler that ships in "Orcas" provides an elegant way to make your code more concise while still retaining the flexibility of properties using a new language feature called "automatic properties". Automatic properties allow you to avoid having to manually declare a private field and write the get/set logic -- instead the compiler can automate creating the private field and the default get/set operations for you.
For example, using automatic properties I can now re-write the code above to just be:
public string FirstName {
get; set;
}
public string LastName {
get; set;
}
public int Age {
get; set;
}
}
Or If I want to be really terse, I can collapse the whitespace even further like so:
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
When the C# "Orcas" compiler encounters an empty get/set property implementation like above, it will now automatically generate a private field for you within your class, and implement a public getter and setter property implementation to it. The benefit of this is that from a type-contract perspective, the class looks exactly like it did with our first (more verbose) implementation above. This means that -- unlike public fields -- I can in the future add validation logic within my property setter implementation without having to change any external component that references my class.
Bart De Smet has a great write-up on what happens under the covers when using automatic properties with the March CTP release of "Orcas". You can read his excellent blog post on it here.
New C# and VB Language Feature: Object Initializers
Types within the .NET Framework rely heavily on the use of properties. When instantiating and using new classes, it is very common to write code like below:
person.FirstName = "Scott";
person.LastName = "Guthrie";
person.Age = 32;
Have you ever wanted to make this more concise (and maybe fit on one line)? With the C# and VB "Orcas" compilers you can now take advantage of a great "syntactic sugar" language feature called "object Initializers" that allows you to-do this and re-write the above code like so:
The compiler will then automatically generate the appropriate property setter code that preserves the same semantic meaning as the previous (more verbose) code sample above.
In addition to setting simple property values when initializing a type, the object initializer feature allows us to optionally set more complex nested property types. For example, assume each Person type we defined above also has a property called "Address" of type "Address". We could then write the below code to create a new "Person" object and set its properties like so:
FirstName = "Scott",
LastName = "Guthrie"
Age = 32,
Address = new Address {
Street = "One Microsoft Way",
City = "Redmond",
State = "WA",
Zip = 98052
}
};
Bart De Smet again has a great write-up on what happens under the covers when using object initializers with the March CTP release of "Orcas". You can read his excellent post on it here.
New C# and VB Language Feature: Collection Initializers
Object Initializers are great, and make it much easier to concisely add objects to collections. For example, if I wanted to add three people to a generics-based List collection of type "Person", I could write the below code:
people.Add( new Person { FirstName = "Scott", LastName = "Guthrie", Age = 32 } );
people.Add( new Person { FirstName = "Bill", LastName = "Gates", Age = 50 } );
people.Add( new Person { FirstName = "Susanne", LastName = "Guthrie", Age = 32 } );
Using the new Object Initializer feature alone saved 12 extra lines of code with this sample versus what I'd need to type with the C# 2.0 compiler.
The C# and VB "Orcas" compilers allow us to go even further, though, and also now support "collection initializers" that allow us to avoid having multiple Add statements, and save even further keystrokes:
new Person { FirstName = "Scott", LastName = "Guthrie", Age = 32 },
new Person { FirstName = "Bill", LastName = "Gates", Age = 50 },
new Person { FirstName = "Susanne", LastName = "Guthrie", Age = 32 }
};
When the compiler encounters the above syntax, it will automatically generate the collection insert code like the previous sample for us.
Summary:
As developers we now have a much more concise way to define objects, initialize them, and add them to collections. At runtime, the semantics will be exactly the same as with today's longer syntax (so you don't need to worry about behavior changes). But now you don't need to type as much, and your code can be more crisp and concise.
In the near future I'll do additional blog posts that examine even more "Orcas" language improvements including Extension Methods, Lambdas, and Anonymous Types. I'll then do a deep dive into LINQ, and show how it takes advantage of all of these features to provide a really elegant way to query and interact with data.
[March 13th Update: I just posted the second article in this series, covering Extension Methods, which you can read here]
Hope this helps,
Scott