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:

    public class Person {

        
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 class Person {
    
        
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 class Person {
        
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 person = new Person();
   
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:

  Person person = new Person { FirstName="Scott", LastName="Guthrie", Age=32 };

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:

   Person person = new Person {
      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:

  List<Person> people = new List<Person>();
            
  
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:

   List<Person> people = new List<Person> {
      
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

43 Comments

  • I think the new features look good but isn't an Object Initializer already present in the language in the form of a constructor?

    Is there a slight danger that some of the "syntactic sugar" being generated will confuse the issue and lead to the same job being done in a multitude of different ways?

    All the LINQ stuff is excellent but a few new features look like they might be generated by developers with not enought to do on a Wednesday afternoon :-)

    cheers,
    D

  • Hi Scott,

    The automatic property feature looks great. I was just wondering, when it comes to adding say validation logic at a later date, will I have to rewrite the property and add my own private field, or will there be some way to access the automatically generated private field?

  • Do you know if automatic properties work with the new get/set-specific protection levels?

  • One question: Is it possible to run the Orcas CTP besides VS2005 without problems on Vista?

    Thanks,
    Andreas

  • im glad to see some more ruby-like goodness is finding its way slowly into c#

  • wow, I really love the property thing. Cant wait to get my hand on them

  • Scott,

    Silly question perhaps, but why is the automatic properties feature a C# feature and not C# and VB.Net feature?

  • Great Post. Keep up the good work.

  • Why should we only use the VPC image with Vista?!

    I have it installed on vista side by side with vs2005 and it works fine.

    Will I have problems removing orcas?

  • This great! and a big time saver. I wonder with these features and DLINQ, simple application development may be in hands of Power Users rather then Programmers and Programmers will be spending more time doing more important stuffs.

  • Scott, if I correctly recall, the collection initializer syntax in some previous CTP's did not require the "new Person" inside the initialization list, it used to be even more compact since it was clear that the collection was for Person objects:
    List people = new List {
    { FirstName = "Scott", LastName = "Guthrie", Age = 32 },
    { FirstName = "Bill", LastName = "Gates", Age = 50 },
    { FirstName = "Susanne", LastName = "Guthrie", Age = 32 }
    };

    If this was the case, would you be able to explain why it had to be changed?

  • Yes yes yes! These are some great features!

  • It will be helpful to have a built in code generator where we could specify just the property names it generates the code. (I gues one could do this now throeugh code snippets and visual studio extensions but I am curious as to what orcas has to offer)

  • Object Initializers are great in JavaScript and I am glad to C# is getting them as well.

  • Slightly (okay, _grossly_) off-topic, but...

    Has anyone else found the Orcas downloads to be excruciatingly slow?

    I usually get 1200KB/s (10mbps) from download.microsoft.com.

    However, when I download any of the Orcas files, I get a maximum of 100KB/s -- it's like MS is throttling those downloads.

    The entire set took over 2 days to download. Anyone else had this problem or found an alternative, faster place to download?

  • The automatic properties are an interesting idea but I don't think they will be all that useful in the real world. The problem is that I rarely have set accessors that say _firstName = value;

    Instead, they usually say something like _firstName = value.Left( 50 ); to trim away data that won't persist to the database because of schema constraints. Or I might throw an exception in the setter if the data won't fit, for example.

    What would have been really cool in the language is a feature that generates the backing field even if I put validation logic in the setter from the start. All you would need is a keyword that has special meaning in the setter, much like the value keyword. I want to write:

    that = value.Left( 50 );

    in the setter to mean set the unnamed backer field to the first 50 characters of the value.

  • I'm very excited for this new version of Visual Studio .NET! Any word on the pending release date/dates for beta/rc?

  • I'm sure there a million people looking forward to the JavaScript intellisence as I am...

    Is there going to be any feature to minimize the javascript. It would be great to be able to remove comments, line breaks, and even rename local variables within .js files at build time.

    I know you are the ASP.NET man..is there something like that already that can be hooked into the build proccess?

  • Nice enhancements. With Orcas supporting multiple Framework versions, will the code above be compliled to the correct selected framework?

    The enhancments are great, but I would avoid them if I need backwards framework compatible class designs.

  • These look like some great improvements. i am glad to finally get these over to vb. Nice work on improving the language

  • Felix:

    I could be wrong, but I swear that I read that any DLL compiled in orcas would work in the current version of .net.

  • Ok now that's just scary.

    I submitted my comment at 10:59 AM, and it was posted to the site around 12:20 PM, and at that precise moment one of my devs reported that the download speed throttled back _up_ to 10mbps.

    Conspiracy? Coincidence? FATE?!

  • Portman: don't tell anyone, but I opened up the connection-speed just for you. :-)

    P.S. Not really - it was just a coincidence. I've been able to get about 300-400kb/sec sustained from my cable modem.

  • It's quite interesting, especially considered against the fact that developers generate exactly the same amount of lines of code no matter what language, framework etc as long as they know the language equally good.
    Everything that reduces the number of lines of code is therefore automatically interesting, however I think the uses of this feature is MARGINALLY at BEST...

    And Scott, PLEASE don't write anything nice about VB, I read on theserverside.net that you're gonna cover also VB9...
    Write the TRUTH!!
    I think it's about time we get to kill this beast... :(


    .t

  • Felix/Roger - all of the language features above will work with .NET 2.0 apps when using multi-targetting.

    They don't require any special instructions nor libraries to support them.

    If you use the LINQ libraries, though, or some of the new types in System.Core.dll then you can only run the code on .NET 3.5.

    Hope this helps,

    Scott

  • Hi SP,

    Yep - in last year's May CTP you didn't need to specify the type name when using collection initializers, which meant you could write code like below:

    List people = new List {

    { FirstName = "Scott", LastName = "Guthrie", Age = 32 },

    { FirstName = "Bill", LastName = "Gates", Age = 50 },

    { FirstName = "Susanne", LastName = "Guthrie", Age = 32 }

    };

    Although nice and terse, it did open up some interesting questions. For example, if you have a collection that is typed as a collection of Interfaces or Abstract Classes, what is the right behavior? Or, if you want to create a sub-class of a non-abstract class, what is the right behavior?

    In the end the team decided to require that you specify the class name as part of the list in order to make it clearer.

    Hope this helps,

    Scott

  • This is awesome! Can't wait to learn more about the new features! Keep up the great work.

  • Just what I have been looking for. Too often when building utility types it seems that the code gets fat due to repeated property blocks. With this candy it makes it much easier to copy- paste/paste/paste and rename a set of simple properties and have thime lay out in a very readably form. This makes teh important code easier to find and visually displays what is happening.

    The initializers also make it easier to obtain a consistent look for repetitve common coding steps. This shuold help to eliminate some types of common keystroke errors and make the code more understandable.

    In assembly languages we have always had macros to do some to do some of the grunt work. This performs a similar service. Enlisting the compiler is always a good idea in my book.

    Great work on Orcas.

  • Scott,

    That's a nice little feature!
    All this "property supporting garbage code" obfuscates useful code.

    With "Automatic Properties" feature our classes would be much cleaner.

  • Interesting features, especially automatic properties, though I have to say off the cuff I prefer Delphi style of properties more, even though they are slightly more work. For example:

    SomeClass = class(TObject)
    private
    _value: String;
    public
    property Value: String read _value write _value;
    end;

    Using that syntax is still cleaner than today's C# 2.0, you don't have to write an explicit getter/setter, you know the exact private variable name AND you can bind against it and at a future date swap out either the getter, setter or both without breaking anything. I think I would have prefered:

    public class Person {

    public string FirstName {
    get _firstname; set _firstname;
    }

    }

    OR even more strange:

    public class Person {

    public string FirstName -> _firstname;

    }

  • I'm always looking for ways to reduce my code, so I'm down with these changes. Additionally, the object initialization is nice to see, and definately a move in the right direction.

    As for properties, I don't care *that* much...I use resharper, which generates all my properties for me anyway.

  • Nice article scott, quick question, with the new object initialization, will it support positional parameters in addition to the named parameters? (similar to parameters on property attributes)

    Ex
    [DataFieldAttribute("Class_ID", TypeName=Number, PrimaryKey=true)]

    Thanks!

  • Pwills: "Has anyone else found the Orcas downloads to be excruciatingly slow?"

    I had a similar experience, but figured something was off - so I restarted the download after about 20 minutes and got a much improved speed.

  • Ok where did my comment go? :-/

  • Totally off-topic question.

    What happened to the sample Wiki application that came with the early versions of Atlas? We were told it would return with later builds, but it disappeared...

  • Hi Scott, great blog.
    I want to support Zack Jones.
    Add automatic properties in VB too, something like this oneliners:

    Public Get Set Property FirstName() As String

    Public Get Set Property LastName() As String

    Public Get Set Property Age() As Integer

  • The naysayers of these "small" features might fail to realize that these are steps towards a more declarative and expressive language. That is always a good thing.

    The object and collection initializers are especially important. Not only do they wipe away some lines of code, they allow what previously demanded imperative constructs in an expression. That's huge! ...and necessary for what LINQ is trying to do with "queries" (another term for expressions). Keep in mind that these features (the two types of initializers) surely didn't exist merely because they seemed like a good enhancement. They were all but required to accomplish what LINQ aims to do.

    As for automatic properties, this is clearly needed to attain something roughly resembling a tuple; another important requirement of LINQ.

    None of these tweaks would be necessary of course if the language designers had just admitted that what they really needed were relations (tables) and such. As a D4 user, I'm spoiled though.

  • Automatic properties are definitely required in C# today, although stuff like ReSharper helps a lot to avoid the too-much-to-type effect of all C-based languages.

    But this implementation seems a little bit dangerous. If I want an abstract property but forget the "abstract" keyword now I will suddenly have a valid statement.

    Why not do it the Boo way? Put an attribute on the field instead, that autogenerates the property. You get both a property and a named field.

    [Property("Name")]
    private string _name;

  • These are really cool new features, I must say.
    However I miss some examples on how to use the new stuff with VB9. p => syntax does not seem to exist in VB9, it must be something else right?

  • One question about Collection Initializers: Will it support IDictionary?

  • Scott, thanks for the answer, I had thought that could be it, but I kind of wished that the compiler checked the declaring collection type and not require the type name if it was a concrete type, assuming all entries were for that type. If I tried to use an interface collection the compiler could reject. I think the concrete type case is way more frequent than the abstract one, so I hoped it could be handled differently. Anyway, thanks for thaking the time to explain it to us.

  • No VB.NET support for automatic properties? Sigh.. perhaps

    Public Automatic Property MyProperty As MyType

    with no further code would be nice..

  • Great article. I would really like to appriciate the things makes easy to write and save a lot of code line. For me jajva script intellisense is a great addition to this. It will help a millions of developers to save a lot of their precious time while writing java script code.
    One issue that i still face is converting inline styles into stylesheets. Is there any way to promote or manage the inline styles to stylesheets?

Comments have been disabled for this content.