C#6: Auto-property Initializers and Expression-Bodied Properties

Last week, I discussed the new null-conditional operators added in C#6. This week, I would like to discuss two features that are awesome but could lead to some confusion: auto-property initializers and expression-bodied properties1.

Auto-initialized Properties

Before C#6, if we wanted to properly define an immutable property that had some expensive initialization, we had to do the following2:

Some people often use the shortcut of an auto-implemented property using the following syntax:

However, defining properties like this means they are still mutable within the class (and its derivations). Using a backing field with the readonly keyword not only ensures that the property cannot be changed anywhere outside of the class construction, it also expresses exactly what you intended. Being as clear as possible is helpful for anyone who has to maintain the code in the future, including your future self.

From what I have read and heard, the main driver for using auto-implemented properties was writing less code. It somewhat saddens me when clarity of intent is replaced by speed of coding as we often pay for it later. Thankfully, both can now be achieved using initializers. Using this new feature, we can condense all that code down to just this:

It is a thing of beauty3. Behind the scenes, the compiler produces equivalent code to the first example with the readonly backing field.

Of course, this doesn't help much if you need to base your initialization on a value that is passed in via the constructor. Though a proposed feature for C#6, primary constructors, would have helped with this, it was pulled from the final release. Therefore, if you want to use construction parameters, you will still need a backing field of some kind. However, there is another feature that can help with this. That feature is expression-bodied properties4.

Expression-bodied Properties

An expression-bodied property looks like this:

This is equivalent to:

Using this lambda-esque syntax, we can provide more succinct implementations of our read-only properties. Consider this code:

Using expression-body syntax, we can write it as:

But for the additional backing field declaration, this is almost as succinct as using an auto-implemented property. Hopefully, this new syntax will encourage people to make their intent clear rather than using the auto-implemented property shortcut when implementing immutable types.

Caveat Emptor

These new syntactical enhancements make property declaration not only easier to write, but in many common cases, easier to read. However, the similarities in these approaches can lead to some confusing, hard-to-spot bugs. Take this code as an example:

Here we have two properties: CurrentDirectory1 and CurrentDirectory2. Both seem to return the same thing, the current directory. However, a closer look reveals a subtle difference.

Imagine if the current directory is C:\Stuff at class instantiation but gets changed to C:\Windows some time afterward; CurrentDirectory1 will return C:\Stuff, but CurrentDirectory2 will return C:\Windows. The reason for this difference is the syntax used. The first property uses auto-initialization; it captures the value of Environment.CurrentDirectory on construction and always returns that captured value, even if Environment.CurrentDirectory changes. The second property uses an expression-body; it will always return the current value of Environment.CurrentDirectory, not the value of Environment.CurrentDirectory on construction of the MyClass instance.

I am sure you can imagine more serious scenarios where such a mix-up could be a problem. Do you think this difference in behavior will be obvious enough during code review or when a bug is reported? I certainly don't and I'm writing this as a way of reinforcing it in my own mind. Perhaps you have already dealt with a bug relating to this; if so, share your tale of woe in the comments.

In Conclusion..

I am by no means intending to discourage the use of these two additions to the C# language; they are brilliant and you should definitely add them to your coding arsenal, but like many things in software development, there is a dark side. Understanding the pros and cons of any such feature is important as it enables us to spot errors, fix bugs, and write good tests. This new confusion in the C# world is just another encouragement to code clearly, test sensibly, and be aware of the power in the tools and languages we use.

  1. No one else seems to by hyphenating "expression-bodied" but it doesn't make sense to me otherwise; what is a "bodied property"? 

  2. Yes, I know that System.Enviroment.CurrentDirectory isn't really expensive; this is for illustrative purposes 

  3. especially if you are keen on making sure your code expresses exactly what you mean 

  4. expression-bodied methods are also possible, but I'm not touching on that in this post 

6 thoughts on “C#6: Auto-property Initializers and Expression-Bodied Properties”

  1. Should there be a (private or protected) setter in "ImmutableProperty" auto-property?

    public class MyClass
    public MyClass()
    ImmutableProperty = System.Environment.CurrentDirectory;

    public string ImmutableProperty

Leave a Reply

Your email address will not be published. Required fields are marked *