C# 6.0 Features You Should Know

Now that C# 6.0 is here, let’s explore the newly introduced features so that we can be aware of what is now available to us, and be able to recognize their meaning in code others have written.


Auto-Property Initializers

As you may know, in C# 3.0 auto-implemented properties were introduced. They provided a concise syntax for property declaration, with the compiler creating a private, anonymous backing field to be used by the property’s get and set accessors.

If you wanted to initialize an auto-implemented property to a non-default value, you would have to do so in a constructor.

Now in C# 6.0, you can initialize an auto-implemented property inline.


Read-Only Auto-Properties

In C# 6.0, you no longer have to declare a setter for auto-implemented properties, providing a new way to implement an immutable property.

Previously with auto-implemented properties you had to declare both a getter and a setter, so if you wanted to make an immutable property, you had to declare  your setter as private. With a private setter, the property is immutable to consumers, but can be changed anywhere within the type. If no setter is declared, the property is immutable everywhere except the type’s constructor.

Besides constructors, auto-implemented properties with no setter can also be initialized in-line using the new auto-property initializer feature we discussed above.


Null-Conditional Operator

Null-conditional operators are perhaps my favorite C# 6.0 feature. They allow for null checking with less code than was previously necessary. Let’s say you have the following classes:

If you wanted to do some processing using Address, you could perform null checking as follows:

You could use the conditional operator to make that more concise:

Now in C# 6.0, you can write it this way:

If student is null, address will simply be assigned null, and no NullReferenceExeception will occur. This becomes more useful with deeper object graphs, as you can handle a chain of conditional member access. For example:

Null-conditional operators are short-circuiting, so as soon as one check of conditional member access returns null, the rest do not take place.


Using Static Directives

Using static directives are a new kind of using directive which brings static members of types directly into scope. Prior to C# 6.0, you would have to qualify the static member with its type.

Now with the using static directive, you can write it as follows:

The intention of this feature is to improve code readability by eliminating unnecessary and redundant type identifiers, but please note that in some situations it could reduce code clarity. For example, in code that is performing file operations, if you were to see the static “Exists” method being used, it might not be immediately obvious if it is File.Exists or Directory.Exists. Sometimes it might be clearer to see the type name, so put some thought into when a using static directive will make a particular piece of code better and when it will not.


String Interpolation

In C#, typically to concatenate strings you would either use the “+” operator or composite formatting with a method such as String.Format. By composite formatting I am referring to a format string with indexed placeholders (format items) and a list of objects to be used in the placeholders.

With interpolated string expressions, you have a string with contained expressions that are replaced with the expressions’ results. You have to prefix your string literal with a dollar sign ($). The expressions you want included in the string are placed inline enclosed in curly braces. The above message would now look like this:


nameof Expressions

Sometimes you need the string name of a variable, type, or member for things such as raising an exception, logging, or firing property changed events. Prior to C# 6.0, you might use a string literal for such purposes.

However, if the student parameter were to be renamed, you would have to remember to also modify the string literal. Now with nameof expressions, you don’t have to use string literals and the compiler will be able to warn you if you are using an incorrect name.

Some examples of where nameof expressions may be useful include:

  • Throwing exceptions during parameter validation
  • Passing an action name when setting up MVC action links
  • Needing to pass the name of a property when firing a property changed event in a class that implements INotifyPropertyChanged
  • Passing the name of a property when registering a XAML dependency property
  • Including a variable, type, or member name when logging

It should be noted that if you provide nameof with a qualified name, the compiler will generate a string for the rightmost name.


Dictionary Initializers

C# 6.0 introduces a new, slightly cleaner syntax for dictionary initialization. The older syntax looks like this:

While the new syntax looks as follows:


Expression Bodied Functions and Properties

In C# 6.0, you can now declare functions and properties as a lambda expression, without the need for a statement block. Intended for simple implementations, the new syntax is more concise in that it eliminates the need for some of the curly braces and the use of an explicit return statement.

Here is a regular method written the old way:

The following gives the same result, but is written as an expression bodied function:


Await in Catch and Finally Blocks

In my opinion, one of the more important C# 6.0 features is the ability to write asynchronous code (use the await keyword) in catch and finally blocks. The limitation of not being able to do so created issues for developers, which made this feature a highly requested one. It is common to want to perform asynchronous operations in catch and finally blocks, such as logging in a catch block, or performing some cleanup asynchronously in a finally block. In C# 6.0, you can now do so.


Exception Filters

Another cool feature of C# 6.0 are exception filters. We have long been able to declare multiple catch blocks to handle different types of exceptions.

Now, through the use of the “when” keyword, we can specify a condition for any catch block. Execution will only drop into a catch block if the condition is satisfied. This allows us to filter exceptions on things other than just the exception type.

This also means that we could have multiple catch blocks for the same exception type, but with different conditions. Previously to achieve this you had to use if statements or a switch statement in a catch block to handle different conditions for a particular exception type.

While this new feature can make exception handling cleaner and more readable, it is more than just syntactic sugar. With exception filters, if a catch block is not entered, then the stack remains intact. In other words, the stack is not unwound, and  information about the current execution state remains. If you place conditional logic inside a catch block for a specific exception type rather than use exception filtering, once the catch block is entered the stack is unwound. If you end up rethrowing your exception in a catch block (i.e. if it doesn’t meet some condition), the Visual Studio debugger will stop there rather than exactly where the actual exception occurred.

The above example assumes you have the debugger set to break only on uncaught exceptions. You could of course configure Visual Studio to break as soon as the exception is thrown, whether it is caught or not. However, sometimes you cannot take advantage of this, such as when you get a crash dump from an application in production. For all of these reasons, it is preferable to use exception filters rather than catching and rethrowing.

As was the case before exception filtering was introduced, the order of your catch blocks matter. Execution will fall into the first catch block that is applicable, so keep that in mind as you write your catch blocks and exception filters.


Wrapping Up

As you have read, some cool new features have been introduced in C# 6.0. The overall theme for this release seems to be one of improving code readability/clarity and simplifying syntax, without introducing major new concepts. Some of what is new completes features that were already in place, such as now allowing await in catch and finally blocks and allowing getter only auto-implemented properties.

I encourage you to visit the .NET Roslyn GitHub repository to see the latest on what is going on with the C# language, including source code for Roslyn, the open-source .NET compiler platform, status on language features, issue reports, and language design notes for future versions of C#.

1 thought on “C# 6.0 Features You Should Know

  • It should be noted that as of this writing (October 20th), we have not officially rolled out Visual Studio 2015 and C# 6.0 yet. Until we do so, you should refrain from using C# 6.0 features as the build machines will have an issue. If you are using Visual Studio 2015 already along with ReSharper, keep in mind that ReSharper may make suggestions utilizing C# 6.0 features, so avoid such refactorings until we have officially rolled out Visual Studio 2015 and C# 6.0.

Leave a Reply

Skip to toolbar