What's new in C# 6.0

C# 6.0 has some cool new features. If you have missed the announcement from Build 2014 then here is the recording of the session. The session talks about Roslyn (the shiny new C# and VB compiler biult in C# and VB respectively) so you if you are not interested then you can skip part that part and jump directly to point where they talk about new features in C#.

Roslyn preview download contains the document listing all the new features being added to C#. But here I am going to talk about the ones I liked most. Feel free to download the preview and take a look at complete list. Before I go into details let me mention that these features are still in preview stage and have not made it to the final version of C# or .NET framework. When they are released, there might be changes to how these features would work or how they look. With that clear, let's look at the new features.

1. Initializers for auto-properties
C# had initializers for fields but such a thing was missing for auto-properties. With C# 6.0 you can have initializers for auto-properties. Following is perfectly valid C# code

public class Product  
{
    public string Name {get; set;} = "Chair";
}

At first glance this might look like not so useful feature. Afterall, why would you define a Product class whose Name property is auto-initialized to "Chair"? This features becomes useful in combination with a new feature called Primary constructors.

2. Primary constructors
Now you can declare construction parameters directly on class or struct. These are called primary constructors. If we had constructor on our Product class as below

public class Product  
{
    public Product(string name)
    {
        this.Name = name;
    }
}

Above constructor can now be written in a short form as below

public class Product(string name)  
{
}

That would save you some key-strokes everytime you create a new class. You must be wondering what happened to the initialization statement from our original constructor. Well, you can get that back with following code

public class Product(string name)  
{
    public string Name {get; set;} = name;
}

What is going on here? The parameter declared in the primary constructor name is available throughout the class for initializing any auto-properties.

3. Field parameters
Sometimes we need to save values of constructor parameters in private fields because they are used elsewhere in the class (if you are still with me then you know that you do not need this feature if you only need to initialize auto-properties). Take a look at following example

public class Customer  
{
    private DateTime dateOfBirth;
    public Customer(DateTime dateOfBirth)
    {
        this.dateOfBirth = dateOfBirth;
    }

    public int Age {get {return     DateTime.Subtract(dateOfBirth).Days/365;}}
}

In the example above, you needed to save value of dateOfBirth into a private field in order to use it to calculate Age later on.

With primary constructor, you are able to get rid of the constructor and still be able to save value of dateOfBirth into a private field as below

public class Customer(private DateTime dateOfBirth)  
{
    public int Age {get {return     DateTime.Subtract(dateOfBirth).Days/365;}}
}

Notice the word private added before the parameter in primary constructor, that makes the parameter a field and keeps it available throughout the class.

4. Declaration expressions
A lot of times programs receieve inputs from clients as strings. In order to convert these inputs to proper types we end up writing follow code all the time.

int count = 0;  
if(int.TryParse(parameter, out count))  
{
    //Some code here
}

Declaration Expressions let you rid of the first statement and write the above code as below

if(int.TryParse(parameter, out int count))  
{
    //Some code here
}

You can even go extra mile and use var instead of int because compiler can infer the type from int.TryParse. Compiler is smart enough to infer the type from type of out parameter if you are calling a function. Following is perfectly valid

void GetCoordinates(out int x, out int y)  
{
    //some code here
}

//call above method
GetCoordinates(out var x, out var y);  

When GetCoordinates is called above, compiler is able to infer the types of the parameters x and y by looking at the defintion of the method being called.

5. Exception filters
As the name suggests, exception filters let you filter the exceptions when they are caught. If you arre writing something like below now

try{...}  
catch(CustomException ex)  
{
    if(ex.Origin.Equals("some origin"))
    { 
        // Do something with exception here
    }

    throw ex;
}

A problem with this code is that when the excpetion is thrown again from catch block, it looses it's stacktrace thus keeping important information from being passed. As highlighted by Markus this is not true (shame on me..!!). You can use just throw instead of thorw ex to retain the stacktrace. Exception filters give you a better way of expression conditions inside catch block. Using exception filters you can achieve same thing as below

try {...}  
catch(MyCustomerException ex) if(ex.Origin.Equals("some origin"))  
{
    //Do something with exception here
    throw ex;
}

Now when the condition inside if block evaluates to true only then catch block is executed. If the condition evaluates tofalse then the exception is not caught and just flows on without loosing the stacktrace.

6. Indexed members and element initializers
You can now initialize a dictionary (or similar data strctures) using the normal element initializer. So code like below

var teens = new Dictionary<int, string>{  
                {11, "Eleven"},
                {12, "Twelve"},
                ...
            }

can now be written as

var teens = new Dictionary<int, string>{  
                [11] = "Eleven",
                [12] = "Twelve",
                ...
            }

Again, this might looks like a very simple feature but it powers come from situations like below

var book = new JsonData();  
book["name"] = "C# for dummies";  
book["ISBN"] = 1223454677;  

This can be written with element initializer as

var book = new JsonData{  
    ["name"] = "C# for dummies",
    ["ISBN"] = 1223454677
    };

And with indexed members you can take this to next level as

var book = new JsonData{  
    $name = "C# for dummies", //$name => ["name"]
    $ISBN = 1223454677        //$ISBN => ["ISBN"] 
    };

7. Other features
There are some other improvements like await in catch and finally blocks, extension add methods in collection initializers, binary liternals and digit separators,using static which I have not mentioned here. This is just about my personal taste. I seem not to use venture into those areas and hence skipped those from this post. Feel free to watch the video I mentioned in the beginning to get a feel of how those features look like.

One more thing, most of these features are just syntactic sugar over what is already present in CLR. This is pure innovation inside C#/VB compiler.

Suhas Chatekar

Discussion

  • Comment with Disqus
  • Comment with Facebook
comments powered by Disqus