DotNetCurry Logo

C# 6.0 What's New

Posted by: Filip Ekberg , on 9/22/2014, in Category C#
Views: 108070
Abstract: C# 6.0 introduces a number of new features that will make it easier for developers to avoid boilerplate code. We also have a new compiler technology called "Roslyn" which allows us hook in” to the compiler and modify certain behavior as our programs compile.

For many years now, Microsoft has been working on a re-write of their C# and VB compiler. We have known about it for some years now and it came as a big surprise recently when Microsoft announced that they would open source their new compilers. Not only has this meant that the work they are doing is transparent, it also means that the community can give feedback on what they see fit. As the language design documents are available on the CodePlex site, any developer wanting to dig into the decisions made when adapting new features, can do so. With the rewrite of the C# and VB compiler, it has become so much easier for the language design team to add new language features. Given that the cost of adding a new feature is substantially smaller than what it was with the old compilers, the language design team can focus on making life much easier for us developers and it does not necessarily mean changing anything from the runtimes perspective.

 

Up until now, all the C# and VB compilers have really been to the consumers, is just a black box. The black box has translated a given syntax into something that is executable or something that we can simply reference. In a way, this has really limited the interoperability of the compiler, which is OK for most people. Although, you will be amazed when thinking about the opportunities that opens up when having the compiler completely open and accessible to the consumer. Before we look at what the next version of C# will look like, let us think around what these changes will do to us; the consumers of the compiler.

Codename “Roslyn”

Microsoft has given the new compilers the codename “Roslyn”, a name that really has a nice ring to it. Imagine being much free in the ways we can interop with compiler, the possibilities are endless as we can “hook in” to the compiler and modify certain behavior as our programs compile. These modifications to the compiler’s behavior are known as analysis and refactoring plugins. When opting in and installing Roslyn you get sample code and solutions. One of these samples lets you detect if your solution contains declarations that could be converted to constants. Another example will let you detect variable names containing a certain characters; this is to educate you in how the compiler APIs work.

Whilst this article is not about how we write these kinds of plugins, it is important to understand the impacts of having a re-written compiler for C# and VB. As it makes it easier for consumers to interop with the compilation and analysis process, it makes it easier for Microsoft to introduce language features and fix possible bugs in the language. Hence, this makes it easier for Microsoft to focus on giving the C# and VB developers the best experience possible when using their languages.

These changes are what we will spend the rest of this article discussing, some of which may not be coming in vNext at all, some of them are already implemented and ready to go. As Roslyn is open source and available on CodePlex, Microsoft invites the community to supply feedback on their design decisions and they are truly listening to the C# and VB community.

What is new in C# 6.0 a.k.a C# vNext

We will not necessarily see new keywords in C# vNext, but we will see semantic differences that will make it easier for developers to avoid boilerplate code. Some of these introduced semantic differences are much awaited and some of them are solving thinner edge cases; they are all very welcomed by the community! As the next version of the compiler is still under development, some of the language features may be taken out, some may be added and some may be delayed to the version after vNext. The evolution of C# is a proof that the language lives, people are using it and it is here to stay.

Primary constructors

Far too often, you will find yourself creating constructors that are simply delivering values to private fields to be used later on in the class. Consider that we have a class representing a Person; a person is required to have a name and an age. This might of course not be the case in reality where we would probably require more information to represent a person, but in this case, this will suffice.

The constructor for the person can be written in a straightforward manner. We are not requiring any particular validation on the data passed to the constructor at this point, as seen in the following code sample.

public Person(string name, int age)
{
    _name = name;
    _age = age;
}

Would it not be great if we did not have to specify this constructor as it is really the default, minimal requirement for our class? Sure enough, it would and there is now a much easier way to define our classes and their primary constructor. It requires us to step out of the scope of the constructor and change the signature of the class. We are now diverting a bit from what we are used to C# looking like.

We need to change the signature of the class to include the parameters we would like to have in our primary constructor, in this case we have the name and the age. The following is what our class will now look like.

class Person(string name, int age)
{
    private string _name = name;
    private int _age = age;
}

The parameters we define on the primary constructor sits on the class declaration, we need to assign these to instance variables. After this, we can use our instance variables _name and _age like any normal instance variable.

In case you want to have more than one constructor, you define the most used (hence primary) on the class declaration and then define the other constructors as we normally do. See the following code sample.

class Person(string name, int age)
{
    private string _name = name;
    private int _age = age;

    private string _address;

    public Person(string name, int age, string address) : this(name, age)
    {
         _address = address;
    }

    public void Speak()
    {
        Console.WriteLine("Hi, my name is {0} and I am {1} years old", _name, _age);
    }
}

Interesting enough, if we open up the compiled assembly in reflector to inspect what code was generated by the compiler, we will see that it is just normal code as we have seen before. This means that there in fact does not need to be a difference in the runtime!

internal class Person
{
    private string _address;
    private int _age;
    private string _name;

    public Person(string name, int age)
    {
        this._name = name;
        this._age = age;
    }

    public Person(string name, int age, string address) : this(name, age)
    {
        this._address = address;
    }

    public void Speak()
    {
        Console.WriteLine("Hi, my name is {0} and I am {1} years old", this._name, this._age);
    }
}

Auto-properties

Properties are so commonly used in C# that you may think there is no optimization left to be done. However, with the introduction of primary constructors we need a way to initialize the properties that we might want to do on instantiation of our class. This is can be done with auto-properties initializers.

As seen in the following code sample, we simply say that the property equals the value we give it

class Person(string name, int age)
{
    public string Name { get; set; } = name;
}

This also works for getters only, as seen in the following code sample.

class Person(string name, int age)
{
    public string Name { get; } = name;
}

We know that properties are backed by fields, and the same will happen here but the compiler will handle it for us. Looking at the generated code by the compiler, we will see that it moves the initialization into the primary constructor and sets the properties backing field to the correct value.

private readonly string k__BackingField;
public string Name
{
    get
    {
        return this. k__BackingField;
    }
}

public Person(string name, int age)
{
    this. k__BackingField = name;
    this._age = age;
}

The auto-property initializers, together with the primary constructors, lets us avoid some boilerplate code. It is not a lot, but it will make a huge difference.

Using statement for static members

If you are using a particular static member a lot, you will find yourself repeating the class name or the path to that static member repeatedly. It gets a bit redundant and it would certainly be great if we could include classes’ static members as a part of our own type, making it easier to access the methods. Consider the usage of Debug.WriteLine or Console.WriteLine for instance. Would it not be perfect if we could define that we are including all static members of Debug and Console, making it usable inside our class without the full path to the static member?

As seen in the following code snippet, this is something that we certainly can do with C# vNext. We simply define that we want to use System.Console and we immediately just have to write WriteLine instead of the full path.

using System.Console;

class Person(string name, int age)
{
    public string Name { get; } = name;
    private int _age = age;

    public void Speak()
    {
        WriteLine("Hi, my name is {0} and I am {1} years old", Name, _age);
    }
}

Again, this change is not as major as introducing async and await, but it will remove the boilerplate code that we always have to write. Another major benefit this gives us is that we can much more easily swap which WriteLine is being used, Debug.WriteLine as opposed to Console.WriteLine means we just have to change the using statement. Of course, we could also introduce the same method inside our class and that would be used instead of the static method. This means if we introduce a method called WriteLine with the same parameter as the one on the static member we previously accessed, the method on our class will be used instead.

You can only do this for static classes, so you cannot for instance do a using for System.DateTime.

Dictionary initializer

When using dictionaries, sometimes you want to initialize them with values just as you can do with arrays and lists. While we have been able to do this earlier in a slightly different flavor (thanks to redditor, skynne for pointing that out), we can now do it using something called dictionary initializers which work very similar to array initializers.

You will see in the following code sample that these new initializers even work with instance variables.

class Person(string name)
{
    private Dictionary _data = 
new Dictionary {["Name"] = name };
}

It will of course also work with the auto-property initializers that we saw previously in this article. These new language features work so nicely together that it makes the language even more pleasant to work with!

class Person(string name, int age)
{
        
    public Dictionary Data { get; } 
= new Dictionary {["Name"] = name };
}

Declaration expressions

Have you ever encountered the out keyword? Then you know that you have to declare it before using it in a method call where there is an out parameter. In many cases, personally I would just like to say that I want the variable to be created inline, instead of having to declare it on the line before.

Consider the following code; normally you would have to declare a variable for the result before calling the actual method.

public void CalculateAgeBasedOn(int birthYear, out int age)
{
    age = DateTime.Now.Year - birthYear;
}

You would end up with something like you can see in this following code snippet, which is still not something that is deal breaking, but it breaks the flow.

int age;
CalculateAgeBasedOn(1987, out age);

We no longer have to do that, as you would most likely have already figured out. Instead we can say that this variable is created inline in the following manner:

CalculateAgeBasedOn(1987, out var age);

It now goes down to one line of code instead of two. Looking at the generated code by the compiler though, it still generates the same code as we have in the first example we looked at, where we are introducing the variable before the call. It is just nice that we as developers do not really have to bother doing it.

Using await in a catch or finally block

If you have caught on with async and await you may have experienced that you want to await for some result in a catch or finally block. Consuming asynchronous APIs are getting more and more common as it is getting much easier with the additions in .NET 4.5. With this being more common, we need a way to ensure that it is compatible with all different scenarios.

Consider logging for instance. You may want to write a file log when you catch an error but not hold up the caller for too long. In this scenario, it would be great to have the ability to await an asynchronous call inside the catch block.

Equally when talking about the finally block, we may want to clean up some resources or do something particular inside the finally block that invokes an asynchronous API. As seen in the following code sample, this is now allowed.

public async Task DownloadAsync()
{
    try
    {}
    catch
    {
        await Task.Delay(2000);
    }
    finally
    {
        await Task.Delay(2000);
    }
}

Filtering Exceptions with Exception Filters

When catching exceptions, you may want to handle the exceptions differently depending on for instance severity in the exceptions. Of course, this has been straightforward before by just having conditional code inside the catch block. Although, would it not be easier if we could filter the exceptions? Indeed, it would, and this has now been introduced as something known as exception filters.

As seen in the following code sample, we simply apply the filter after we have said what exception we are catching.

try
{
    throw new CustomException { Severity = 100 };
}
catch (CustomException ex) if (ex.Severity > 50)
{
    Console.WriteLine("*BING BING* WARNING *BING BING*");
}

For this example to work, a class called CustomException was introduced with only one property on it called Severity. In this case, we are looking for a severity over 50, what happens when the severity is less than 50? The exception will not be caught. To fix this we can introduce another catch block after it, just as we have been able to do before when catching multiple different exceptions.

try
{
    throw new CustomException { Severity = 100 };
}
catch (CustomException ex) if (ex.Severity > 50)
{
    Console.WriteLine("*BING BING* WARNING *BING BING*");
}
catch (CustomException ex)
{
    Console.WriteLine("Whooops!");
}

Keep in mind that the order matters, you want to order them descending where the first one is the most specific one going down to less specific filters as seen in the next code sample.

catch (CustomException ex) if (ex.Severity > 50) {}
catch (CustomException ex) if (ex.Severity > 25) {}
catch (CustomException ex) {}
catch (Exception ex) {}

Planned Features in C# 6.0

Up until now, we have looked at features that have been implemented in the new compiler, features that you can experiment with yourself by either downloading the extension for Visual Studio or installing the CTP of Visual Studio 14. There are more features on the table though, some of the features have been talked about from the beginning of the language design but have later been cancelled, or only introduced in VB instead of C# as C# may already have had it or it would not make any sense to have it in C# to start with.

The rest of the features that we will look at are either planned, to be implemented or are just on the table and might get into the next version of C#. There is no guarantee that a feature that is planned to be implemented will be done by the time of the next language release. It might even end up being completely cancelled as there may be no point in implementing it. Keep in mind though that the language design team adds their documents from their design meetings to CodePlex, so that all those developers interested in the future of C# can follow along and see what is in it for the future.

Null propagation

While this feature is actually already done, it is not currently available in the extension for Visual Studio available for download. Personally, it has happened so often that I do not think I can count on my fingers how many times I have gotten a null reference exception due to forgetting to do a null check on one of the properties I need to use, especially when it is a long path on a certain object that leads down to the property that I want to use.

Consider that we have a person, the person has an address and we want to get the street name. The address is represented by an object and if the person has not given us their address, the property for the address on the person is null. Now you would most likely think that this is bad design, surely enough it may be. If you would take up the argument with a domain-driven development evangelist, they would tell you that the person is not a valid object until all the fields have their correct values.

Being stuck in the world of nulls, we need a better way of handling these type of scenarios and this is where null propagation comes into play. Have a look at the following code sample. It is a representation of what we just talked about; the person with an address.

class Person
{
    public string Name { get; set; }
    public Address Address { get; set; }
}

class Address
{
    public string AddressLine1 { get; set; }
    public string AddressLine2 { get; set; }
}

We can now create an instance of a person, without giving it a valid address, as seen in this code sample.

 

var filip = new Person
{
    Name = "Filip"
};

Console.WriteLine(filip.Address.AddressLine1);

Of course, this will throw a null reference exception. Fixing this previously would mean we had to add inline null checks, which could be pretty messy as seen in the following code sample.

Console.WriteLine(filip.Address == null ? "No Address" :  filip.Address.AddressLine1);

With null propagation, we simply have to add one character to fix this problem, which is nice on the eyes.

Console.WriteLine(filip.Address?.AddressLine1 ?? "No Address");

This will be converted to what we saw previously, thus the entire expression will be returned as null if one of the null propagations detects null. This will be extremely handy at times and hopefully we will see less crashes due to invalid null checks.

Binary literals and Digit separators

Most of us probably do not write binary numbers on a daily basis, however for those of us who do, there is a planned feature to make it even easier to write binary literals in our code. If you would like to write the binary representation of eight, you could simply define that as 0b00001000. That looks pretty much like the way we write hexadecimal numbers.

Speaking of hexadecimal numbers, we may also get something called digit separators. This will be used to separate digits to make it easier on the eyes. Consider having the hexadecimal representation 0xFF00FAAF. To make this easier to read, it is planned to introduce a separator. The separator will make the hexadecimal representation look a bit different, but much easier to read as you see here 0xFF_00_FA_AF.

Expression-bodied members

If we are using primary constructors, we may want to introduce a property in our class that calculates something every time based on these values. It could be calculating the area of a rectangle based on the width and height passed to the rectangle primary constructor, or it could be calculating something differently.

Expression-bodied members means that we can have members in our class that have an expression body, and is straightforward. As always when introducing expressions and their bodies, we are using the fat arrow syntax.

As seen in the following example, we have a public member that will evaluate an expression when it is called that calculates the area of a rectangle.

class Rectangle(int width, int height)
{
    public int Area => width * height;
}

Event initializers

Most of us are using events on a daily basis and it is quite irritating that when we have the power of initializers, we cannot apply the same pattern when it comes to events. This means that we have not been able to initialize the events in our normal object initializers.

It is one of the smaller changes, but it makes all the difference in the world. As seen in the following code sample, we have a web client that informs us when a download is completed. We could do this using an object initializer and initialize the event directly in the object initialization.

var client = new WebClient
{
    DownloadFileCompleted += DownloadFileCompletedHandler
};

NameOf operator

In some cases, you may want to retrieve the name of something in your code, be it a member of your class or a static path. The new operator NameOf will let us do this. The result of calling NameOf(Debug.WriteLine) would be WriteLine. This is neat as it does not force us to put strings in our code to represent the name of a member, thus keeping refactoring capabilities intact!

Field targets on auto-properties

Properties are so widely used as you may still think there is nothing left to improve, however so far it has been impossible to adjust the declaration of the backing field of a property without manually setting it up yourself. An example of how the field targeting would work can be seen in the following code sample.

[field: NonSerialized]
public int Age { get; set; }

In this case, we would say that the backing field of Age would not be serialized.

Features that may show up in C# 6.0

As stated earlier, there are features that may or may not show up in the language with the next release. We will not go in to the features that we are not sure of how they will be implemented:

  • Semicolon operator
  • Using params with IEnumerable
  • Constructor inference
  • String interpolation

Since we are not sure about the implementation of these features, it would be pointless to get your hopes up on the above features. They would be much welcomed into the language, but it is certainly not a deal-breaker if they are left out.

Maybe it is something for the version after C# 6.

Conclusion

If you are ready to try these new language features, you can download the CTP version of Visual Studio 14. The RTM will most likely be released in 2015. There are now a great number of features already implemented; having the compiler written in C# and VB is great for maintainability and extensibility. As seen in the examples given, the language is very much alive and evolving all the time. I personally cannot wait for the next version of C# to come out and be the norm in my work day.

P.S: For those who prefer watching a video, Filip has created a C# 6.0 New Feature YouTube video that you can watch here https://www.youtube.com/watch?v=BA3sL783_Co. Disclaimer: Average Recording/Audio Quality, so put on your headphones

UPDATE: On October 2, 2014, the language design team announced to withdraw two features from C# 6.0. This change withdrew Primary Constructors and Declaration Expressions. This helps them focus on the other language features and makes sure they deliver a high quality refinement of the C# programming language. The announcement is available here: https://roslyn.codeplex.com/discussions/568820

Recommended Articles
Author
Filip is a Microsoft Visual C# MVP, Book author, Pluralsight author and Senior Consultant at Readify. He is the author of the book C# Smorgasbord, which covers a vast variety of different technologies, patterns and practices. Follow Filip on twitter @fekberg and read his articles on fekberg.com


Page copy protected against web site content infringement by Copyscape




Leave us some feedback
comments powered by Disqus
Comment posted by Eugene on Monday, September 22, 2014 4:01 AM
Please correct the title of the paragraph: Codename “Rosyln”
Comment posted by Carol on Monday, September 22, 2014 4:20 AM
@Eugene: Sorry about that. Fixed! Thanks!
Comment posted by Fred on Monday, September 22, 2014 7:00 AM
Typo/Grammar error: "Null's" should be "Nulls"
Comment posted by Suprotim Agarwal on Monday, September 22, 2014 8:02 AM
Thanks Fred, made the correction!
Comment posted by Phylos on Monday, September 22, 2014 8:22 AM
C# edges closer and closer to F# with every new release.
Comment posted by Ben on Monday, September 22, 2014 9:19 AM
What is the semicolon Operator?
Comment posted by Filip Ekberg on Monday, September 22, 2014 9:25 AM
Hi Ben,

The semicolon operator is about evaluating a statement when for instance declaring a variable as one statement while still letting you do more things inside the statement.

Here's an example:

    var y = (var x = Foo(); Write(x); x * x);

Everything between the first ( and the last ) will be evaluated as one statement before the value is assigned to `y`. In the above example, first `x` is set to whatever Foo returns, then we return the result of `x` multiplied by `x`.

Comment posted by Brandon on Tuesday, September 23, 2014 12:54 AM
Great read. I wish I could use some of these right now. However, I doubt I would use the semicolon operator. Abstract that stuff out for clarity.
Comment posted by Sergey on Tuesday, September 23, 2014 12:58 PM
These two lines are not equivalent when filip.Address.AddressLine1 == null

Console.WriteLine(filip.Address == null ? "No Address" :  filip.Address.AddressLine1);
Console.WriteLine(filip?.Address.AddressLine1 ?? "No Address");
Comment posted by Filip Ekberg on Tuesday, September 23, 2014 4:54 PM
Hi Sergey,

That is correct! There's even more "bugs" which null propagation would fix. Consider `filip`, `Address` and `AddressLine1` all being null, the first line doesn't check that!

    filip?.Address?.AddressLine1 ?? "NoAddress"

The above would be a better way of doing it, especially if `filip` is passed from somewhere else.

Good spotted!
Comment posted by Sinix on Wednesday, September 24, 2014 3:25 AM
Hi!

filip.Address == null ? "No Address" :  filip.Address.AddressLine1;
equals to
filip.Address?.AddressLine1 ?? "No Address",
not
filip?.Address.AddressLine1 ?? "No Address".

The last one will be rewritten to smth alike
filip == null ? "No Address" :  filip.Address.AddressLine1;

Comment posted by Sinix on Wednesday, September 24, 2014 4:05 AM
Hi!

filip.Address == null ? "No Address" :  filip.Address.AddressLine1;
equals to
filip.Address?.AddressLine1 ?? "No Address",
not
filip?.Address.AddressLine1 ?? "No Address".

The last one will be rewritten to smth alike
filip == null ? "No Address" :  filip.Address.AddressLine1;

Comment posted by Filip Ekberg on Wednesday, September 24, 2014 8:48 PM
Hi Sinx,

You're indeed correct! Thanks for clarifying what Sergey was talking about.
Comment posted by Suprotim Agarwal on Wednesday, September 24, 2014 9:52 PM
@Sergey @Sinix Thanks for pointing that out. Fixed it.
Comment posted by MBR on Saturday, September 27, 2014 11:22 AM
+1 for init'd auto props. And +1 for ?. and constructor inference -- hope they make it!

Being able to say:
    var foo = new Tuple("s",1, new bar(1,2))
instead of
    var foo = new Tuple<string, int, MyClass<int,int>>("s",1, new bar(1,2))
Is a godsend.
This isn't just a matter of saving characters, but makes it much less of a refactoring nightmare.
Too bad first-class tuple c'tor syntax isn't there too...
Comment posted by Vanessa on Tuesday, February 3, 2015 10:52 PM
If you don't have vs2015 beta and want to try and experiment with these features you can do it online : http://volatileread.com/Wiki/Index?id=1075