SJCNet

SJCNet is the home of architect/developer/techie, Simon Coope.

What's New in C# 6? - Overview

Here's a post I started some months ago and never finished. Now I'm working to get back to regular blogging I thought I should try and finish it.

C#6 - Overview of Changes

With the RTM release of Visual Studio 2015 earlier last year (20th July 2015) we've also got C#6. The following post is an overview of the updates to the new C# langulage specification.

I've also created a really simple solution to include all the code examples I've created. This can be found here on Github.

Static Using Syntax

This feature allows us to invoke a static method without the need for explicit references.

using SJCNet.CSharp6.Utility;
using static System.Console;

namespace SJCNet.CSharp6.StaticUsingSyntax
{
    public class Example : IExample
    {
        public void Execute()
        {
            WriteLine("This is written using a static using statement.");
        }
    }
}

I'll wait until I've used this more to see if I like it, but initially I wonder if it will get confusing without explicitly knowing the object the method is on (e.g. Console.WriteLine("blah")).

Auto Property Initializers

Now we can add initializers for auto-properties just as we can with field initializers. In this case the initializer initalizes the backing field for the property, but interestingly it doesn't run through the setter of the auto-property. Also the auto-property cannot reference this because the initialization is executed before the object is fully initialized.

public string GivenNames{ get; set; } = "John";

public string FamilyName { get; set; } = "Smith";

public int Age { get; set; } = 30;

You can also declare auto-properties without a setter. In this case the backing field is implicitly declared as readonly. So the value can only be initialised on the property or in the objects constructor.

public Person(Genders gender)
{
    this.Gender = gender;
}

public Genders Gender { get; } = Genders.Male;

Index Initializers

C# 6 also brings index initialization into the mix. Before we initialized a dictionary as follows:

var output = new Dictionary<string, string>()
    {
        {"Father", "John Smith"},
        {"Mother", "Jane Smith"},
        {"Daughter", "Sally Smith"},
        {"Son", "Bertie Smith"},
    };

Now we're able to take advantage of the cleaner syntax of index initialization:

var output = new Dictionary<string, string>()
    {
        ["Father"] = "John Smith",
        ["Mother"] = "Jane Smith",
        ["Daughter"] = "Sally Smith",
        ["Son"] = "Bertie Smith"
    };

It's really important to note that using index initialization calls the indexer method, whereas the old approach calls the add method. This means that for the new approach initializing with duplicate keys will create the index if it doesn't already exist or overwrite the value if the index does exist. However, the old approach would throw an error because you've tried to add a duplicate key. This is best shown in the example as follows:

private Dictionary<string, string> DuplicateInitializationUsingNewWay()
{
    // Output is a dictionary of one item with a key of "Father" and a value of "Jane Smith".
    var output = new Dictionary<string, string>()
    {
        ["Father"] = "John Smith",
        ["Father"] = "Jane Smith",
    };

    return output;
}

private Dictionary<string, string> DuplicateInitializationUsingOldWay()
{
    // Throws an error
    var output = new Dictionary<string, string>()
    {
        {"Father", "John Smith"},
        {"Father", "Jane Smith"},
    };

    return output;
}

More interestingly index initialization isn't just for dictionaries. It can be used for any object that supports an indexer.

private List<string> InitializeNonDictionaryType()
{
    var array = new[] { "John Smith", "Jane Smith", "Incorrect Input", "Bertie Smith" };
    var output = new List<string>(array) { [2] = "Sally Smith" };
    return output;
}

This also means that if a type doesn't have an Add method but does have an indexer method we can still initialize in this way.

String Interpolation

Prior to C#6.0 we would typically concatenate strings or use String.Format to replace placeholders in a string with parameters. Now in C#6.0 we can use arguments as placeholders which is much cleaner!

var person = new Person("John", "Smith", 29, Genders.Male);

// Previous Approach
WriteLine(string.Format("Hello, my name is {0} and I am {1} years old!", person.GivenNames, person.Age));

// New Approach
WriteLine($"Hello, my name is {person.GivenNames} and I am {person.Age} years old!");

Note the use of the $ which prefixes the string, and the curly braces that embed the arguments.

Also, string interpolation is transformed at compile time to invoke the equivalent String.Format call. This means we still have localisation support.

NameOf Operator

The nameOf expression is simply an advanced type of string literal where the compiler checks that the member you're naming is a valid type. So instead of using "magic" strings as we may have in the past, we can now use the nameOf operator which means we can reliably refactor and we have the compile time checking to reduce the likelihood of runtime errors or difficult to understand output.

I see this type of thing as being mainly useful when reporting errors, debug/trace information and logging.


var person = new Person(Genders.Male);

// Null reference check
if (person.GivenNames == null)
{
    // Previous approach
    WriteLine("GivenNames is null");

    // New approach
    WriteLine($"{nameof(person.GivenNames)} is null");
}

Exception Filters

Exception filters allow us to specify a condition on the catch block. For example:


var httpStatusCode = "404";
WriteLine($"Http Status Code = {httpStatusCode}");

// Previous Approach
try
{
    throw new Exception(httpStatusCode);
}
catch (Exception ex)
{
    switch(ex.Message)
    {
        case "401":
            WriteLine("Unauthorized");
            break;
        case "402": 
            WriteLine("Payment Required");
            break;
        case "403":
            WriteLine("Forbidden");
            break;
        case "404":
            WriteLine("Not Found");
            break;
    }
}

// New Approach
try
{
    throw new Exception(httpStatusCode);
}
catch (Exception ex) when (ex.Message.Equals("401"))
{
    WriteLine("Unauthorized");
}
catch (Exception ex) when (ex.Message.Equals("402"))
{
    WriteLine("Payment Required");
}
catch (Exception ex) when (ex.Message.Equals("403"))
{
    WriteLine("Forbidden");
}
catch (Exception ex) when (ex.Message.Equals("404"))
{
    WriteLine("Not Found");
}

This means we can now conditionally enter a catch block, rather than enter the catch block and test to see which condition meets our exception.

Expression-Bodied Members

Expression bodied members are a change to method and property declarations, where instead of creating a statement block we now define the body using the lamdba expression syntax.

An expression bodied member must include a name, return type and return expression. It can also use all the existing modifiers (e.g. virtual, override, static, implicit/explicit operators, etc.) but can't be used for abstract methods, which of course cannot declare a method body.

Expression-Bodied Properties

Expression-bodied properties can only be read-only. So the expression represents the get method and so the property can't have a set method.

// Block-Bodied Property
public string FullName
{
    get
    {
        return $"{this.GivenNames} {this.FamilyName}";
    }
}

// Expression-Bodied Property
public string FullName => $"{this.GivenNames} {this.FamilyName}";

In the above example, we can see the FullName property is an expression-bodied member that's built using the GivenNames and FamilyName properties.

As far as I can see the expression-bodied property is just syntactic sugar as it appears to generate the same IL at runtime as composing the full property body. However, it does feel more elegant and in my opinion is easier to read and just a generally neater approach.

Expression-Bodied Methods

Expression-bodied methods take it a step further, and allow us to supply an expression for the body of a method. So now we're able to use parameters and async expression-bodied methods.

// Block-Bodied Method
public string Greet(string greeting)
{
    return $"{greeting}, my name is {this.FullName} and I am {this.Age} years old.";
}

// Expression-Bodied Method
public string Greet(string greeting) => $"{greeting}, my name is {this.FullName} and I am {this.Age} years old.";

Again, the expression-bodied method implementation is syntactic sugar as it generates the same IL as the block-bodied method. But as with the properties implementation it's neater and I find it easier to read for simple expressions.

However, there are limitations with expression-bodied members. For example, you can't use branching statements (i.e. if, else and switch). Though you can use the ternary operator. You also can't use for, foreach, while and do loops. Though again you to replicate these statements using LINQ queries.

So all in all, as I stated previously I think expression-bodied members are useful to make your code more readable, neater and therefore easier to understand. However, I intend to stick to using this approach for simple expressions as innappropriate use will have a distinctly adverse effect on readability.

Null Conditional Operators

Null conditional operators allow us to test for nulls before performing member or index operations. These operators therefore help us to write less null-handling checks and therefore less code.

var people = new List<Person>
{
    new Person("Barry Clive", "Jones", 57),
    null,
    new Person("Smith")
};

// Null Conditional Member Operator
if (people?.Count() > 0)
{
    for (var i = 0; i < people.Count; i++)
    {
        // Null Conditional Index Operator
        var person = people?[i];

        // Null Conditional Member Operator
        Logger.Write($"Full Name: {person?.FullName}");
    }
}

The above example shows the member null conditional operator (e.g. person?.FullName) and the index null conditional operator (e.g. people?[i]).

Await in Catch and Finally Blocks

C#6 also brings the ability to use await expressions in catch and finally blocks. This can be really useful if we want to log our expressions without blocking the current thread.

public async void ExecuteAsync()
{
    try
    {
        DoSomeWork();
    }
    catch (Exception ex)
    {
        Logger.Write("Catch Await: Start");
        await LogAsync(ex.Message);
        Logger.Write("Catch Await: End");
    }
    finally
    {
        Logger.Write("Finally Await: Start");
        await LogAsync("In finally block");
        Logger.Write("Finally Await: End");
    }
}

public void DoSomeWork()
{
    Logger.Write("DoSomeWork: Start");
    Thread.Sleep(1000);
    throw new Exception("DoSomeWork failed");
}

public async Task LogAsync(string message)
{
    await Task.Factory.StartNew(() =>
    {
        Logger.Write("LogAsync Start");
        Thread.Sleep(1000);
        Logger.Write($"LogAsync Message: {message}");
        Logger.Write("LogAsync End");
    });
}

The following example shows an example where we can execute asynchronous method calls from the catch and finally blocks without blocking the program execution.

All in all I'm pretty excited about the updates to the C# language syntax as most of the changes seem well thought out and inline with what the majority of the community want to see.

Hope that was helpful for someone!

Author image
About Simon Coope
Sydney, Australia Website
Experienced developer/consultant. Loves all things development, technology, gadgets, football and running.