What’s New in C# 6.0
Introduction
Visual Studio 2015 will be officially RTM on July 20th, Microsoft announced. With it comes a new version of the .NET framework (actually, two), .NET 5.0, and inside of it, support for a new version of the C# language, C# 6.0. Yeah, the numbers don’t match, keep that in mind!
If you are curious, Visual Studio 2015 will also include .NET 4.6. This will provide a migration path for those of us who are stuck with .NET 4.x code and can’t afford the breaking changes that .NET 5 will introduce. More on this in a future post.
For the moment, I am going to talk about what’s new in C# 6.0, in no particular order. Some of you may be familiar with parts of it, and some might even be expecting a bit more, but unfortunately, some features that were previously announced didn’t make it to the final version.
Auto-Property Initializers
It is now possible to provide an initial value for auto-implemented properties without resorting to a custom constructor. Here’s how, in two examples:
public class MyClass
{
public int MyNumericProperty { get; set; } = 1;
public bool MyBooleanOtherProperty { get; set; } = (MyNumericProperty > 0);
}
Did you notice how we can even use simple expressions in the initialization block? Pretty cool!
Getter-Only Auto-Properties
Similar to the previous example, we can now have getter-only properties, that is, without any kind of setter. We just need to provide an initialization value:
public class Math
{
public static double PI { get; } = 3.14159265359;
}
Alternatively, we can define its value in a constructor:
public class Math
{
public static double PI { get; }
static Math()
{
PI = 3.14159265359;
}
}
Expression-Bodied Methods and Properties
Not sure of the actual interest of this one, but, hey, it’s here: the ability to supply the body for properties and methods from simple expressions.
public class MyClass
{
public int Add(int a, int b) => a + b;
public string TimeOfDay => DateTime.Now.TimeOfDay;
}
nameof Expressions
nameof expressions avoid the need to hardcode names or use complex reflection or LINQ expression tricks. It’s better to show it in action:
void ThrowArgumentNullExceptionUsingNameOf(string param1)
{
throw new ArgumentNullException(nameof(param1)); //"param1"
}
var className = nameof(MyClass); //"MyClass"
var propertyName = nameof(myInstance.Property); //"Property"
Exception Filters
This is about the ability to filter exceptions in a catch block based on more than the exception class itself:
try
{
//…
}
catch (MyException ex) if (ex.Code == 42)
{
//…
}
catch (MyOtherException ex) if (Check(ex))
{
//…
}
Notice that you can use methods in the filter clause, not just simple comparisons.
String Interpolation
This is one of my favorites: adding field, variable and method calls in the middle of a string, and having it interpreted at runtime:
var variable = $"This is i: {i}";
var property = $"A property: {this.Property}";
var method = $"Filename: {Path.GetFullPath(filename)}";
var format = $"Short date: {DateTime.Now:d}";
Very similar to String.Format, but easier to use.
Null-Conditional Operator
Another personal favorite! No need for repeated null checks in deep property accesses or event handlers, the compiler takes care of it for us:
var p = myInstance?.myProperty?.myNestedProperty;
public event EventHandler MyEvent;
public void OnMyEvent(EventArgs e)
{
this.MyEvent?.Invoke(this, e);
}
If either myInstance or myProperty are null, null will be returned. It even works for events, as you can see.
Using Static Members
Besides bringing namespace types into context, using can now be used to do the same with static methods! For instance, take Console.WriteLine:
using WriteLine = System.Console.WriteLine;
//static method WriteLine only
WriteLine("Hello, World");
using System.Linq.Enumerable;
//all extension methods of Enumerable
var numbers = new [] { 1, 2, 3 };
var even = numbers.Where(x => (x % 2) == 0);
This will come in handy, to avoid type clashes. We just import the methods we’re interested in.
Index Member Syntax
A new notation for creating dictionary instances is introduced:
var dict = new Dictionary<int, string>
{
[1] = "one",
[2] = "two"
};
Async in Catch and Finally Blocks
Using async in a catch or finally block is now valid:
try
{
//...
}
catch (Exception exception)
{
await LogAsync(exception);
}
finally
{
await ReleaseAsync();
}
Extension Add Methods in Collection Initializers
Starting with C# 4 (.NET 4), we could use an explicit enumeration syntax for creating collections (actually, any kind of classes that provided an Add method with a compatible parameters). Now extension methods are supported as well:
public static void Add(this ICollection<string> col, int i)
{
col.Add(i.ToString());
}
var col = new List<string>{ 1, 2, 3 };
Here we are creating a List of strings, but we have an extension method that knows how to add integers to collections of strings.
Conclusion
All weighed up, there are some nice additions, others I don’t really see the point, but eventually I may.
You can read everything about it in the Roslyn site at GitHub: https://github.com/dotnet/roslyn and https://github.com/dotnet/roslyn/wiki/Languages-features-in-C%23-6-and-VB-14.