August 30, 2015

C# 6: what's new

C# 6 was officially released about month ago, but it was in "preview" mode since the last year. So I am sure that everyone who wanted, can touch it and see all the new features. If not -  here's the list of updates in the latest version of C#.

Along with C# Microsoft released VB 14. They are both part of the Roslyn compiler, who is available on github.

String Interpolation
C#6
var str = $"Hello, {name}. You clicked {clickCount} time{{s}}";
It's good alternative to String.Format function. The same piece of code on C# 5 will looks like this
C#5
var str = String.Format("Hello, {0}. You clicked {1} time{s}", name, clickCount);


Null-Conditional operator (?.)
C#6
var result = Foo()?.Length

var length = str?.Length ?? 0;
It's also called null-propagating operator or "Elvis" operator. As previous feature it's only the syntactic sugar for accessing a member or invoking a method on a value if it's not null.
C#5
int result;
if(Foo() != null)
{
    result = Foo().Length;
}

int length;
if(str != null)
{
    length = str.Length;
}
else
{
    length = 0;
}

//or

var length = str != null ? str.Length : 0;

nameof operator
C#6
Console.WriteLine(nameof(flags));
For me it's the killer feature of this release. There are many cases when you can use this operator. Moreover it's evaluated at compile-time to produce a string.
There is no equivalent in C#5, but we can write run-time synonym
C#5
Console.WriteLine(typeof(flags).Name);

Default values to auto properties
C#6
private class Man
{
    public string Name { get; set; } = "Alex";
    public uint Age { get; set; } = 25;
}
Now you can assign property values right in the place where they are declared, without creating constructor or special init method.
C#5
internal class Man
{
    public string Name { get; set; }
    public uint Age { get; set; }

    public Man(string name, uint age)
    {
        Name = name;
        Age = age;
    }
}

Static imports
C#6
using static System.Console;
using static System.Math;

class Program
{
    static void Main()
    {
        WriteLine(Pow(2.0, 3.0));
    }
}
Now using directive has one more use case:
  • allows you to access static members of a type or namespace without having to qualify the access with the type name or namespace.
C#5
using System;

class Program
{
    static void Main()
    {
       Console.WriteLine(Math.Pow(2.0, 3.0));
    }
}
Just a recap, here's another usages of using directive:
  • allows the use of types in a namespace so that you do not have to qualify the use of a type in that namespace;
  • creates an alias for a namespace or a type. This is called a using alias directive.

Expression-bodied members
С#6
public string Name => "Alex";

[HttpGet]
public bool Get(string id) => CheckUserExist(id);
This is quite ambiguous improvement. It allows you to write body of the properties and methods as a lambda expression. But in my opinion old variant is more clear for understanding, especially for methods.
С#5
public string Name
{
    get
    {
        return "Alex";
    }
}

[HttpGet]
public bool Get(string id)
{
    return CheckUserExist(id);
}

Await in catch/finally
C#6
try
{
    throw new Exception();
}
catch (Exception e)
{
    await HandleException(e);
}
finally
{
    await Finalize();
}
In C#5 you can use await only in try section. Now you able to do it in the catch and finally blocks. That makes code more asynchronous, without writing complicated code.

Exception filters
C#6
try
{
    throw new IndexOutOfRangeException("There is no such buyer in the array");
}
catch (Exception e) when (e.Message.Contains("buyer")) //in preview versions was if instead of when
{
    WriteLine("buyer error");
}
catch (Exception e) when (e is IndexOutOfRangeException) //example for educational purpose only
{
    WriteLine("IndexOutOfRangeException");
}
Now you can filter exception not only by exception type but by everything you want. When exception occurs, it looks the nearest catch block. If catch expression evaluates to true, code in the catch block will run, if not - exception will search another catch block satisfying its exception type. But be careful, if no filter satisfies the conditions, unhandled exception will be thrown, so it's better to add catch block without any conditions at the end.

Constrcutor assignment to getter-only autoprops
C#6
internal class Man
{
    public string Name { get; }

    public Man()
    {
        Name = "Alex";
    }

    //or just

    public Name { get; } = "Alex";
}
Probably, it's the least mentioned feature. It allows you to set a value to getter-only auto-implemented properties from constructor, or you can use set value as it's described above, using another new possibility of C#6.

No comments:

Post a Comment