2017-03-18

C# Version 7 New Features

Visual Studio 2017 shipped earlier this month. Visual Studio itself has new features, but this article is concentrating on the C# programming language. I made a previous post on what they were talking about early in the development of C# version 7, but now we get to see what actually made it into the final product.

While these features are in the shipping version, there is yet to be a formal specification of the language for C# version 7. The last formal specification was for C# version 5. It would be good if they could get the spec updated.

This article describes the new features: https://blogs.msdn.microsoft.com/dotnet/2017/03/09/new-features-in-c-7-0/

1) Out variables. When specifying out variables, the definition of them can be placed at the point where they are called. We used to have to do this:

public void PrintCoordinates(Point p)
{
    int x, y; // have to "predeclare"
    p.GetCoordinates(out x, out y);
    WriteLine($"({x}, {y})");
}

but now we can do this:

public void PrintCoordinates(Point p)
{
    p.GetCoordinates(out int x, out int y);
    WriteLine($"({x}, {y})");
}

This is very nice especially for things like a TryParse method.

2) Pattern matching. This is now valid code:

switch(shape)
{
    case Circle c:
        WriteLine($"circle with radius {c.Radius}");
        break;
    case Rectangle s when (s.Length == s.Height):
        WriteLine($"{s.Length} x {s.Height} square");
        break;
    case Rectangle r:
        WriteLine($"{r.Length} x {r.Height} rectangle");
        break;
    default:
        WriteLine("<unknown shape="">");
        break;
    case null:
        throw new ArgumentNullException(nameof(shape));
}

The order of interpreting case statements has changed. Before it was undefined the order they were executed. Now, because order matters as the two Rectangle cases above show, case statements are executed in order, except the default is always executed last, regardless of order.

There is more stuff that matching can do.

3) Tuples. I think this is the one that might affect my code the most as it gives the ability to return more than one value from a method call. The Lua programming language has a way of doing that, and I found it cool. Tuples is actually more powerful than what Lua can do. Example of a declaration:

(string first, string middle, string last) LookupName(long id)
{
    // stuff
}

Then can be called with:

(first, middle, last) = LookupName(id2);

There are more variations on this.

4) Local functions. A method that is scoped so it is only accessible to an outer method. This is likely to get used incorrectly, so be careful. Here is a valid use:

public int Fibonacci(int x)
{
    if (x < 0) throw new ArgumentException("Less negativity please!", nameof(x));
    return Fib(x).current;

    (int current, int previous) Fib(int i)
    {
        if (i == 0) return (1, 0);
        var (p, pp) = Fib(i - 1);
        return (p + pp, p);
    }
}

5) Underscores in constant declarations of numbers. These are all valid now:

var d = 123_456;
var x = 0xAB_CD_EF;
var b = 0b1010_1011_1100_1101_1110_1111;

The underscores are ignored, but may improve readability of some numbers.

6) Ref returns and locals. Methods can return information by reference instead of by valid. See the example in the link above. This is particularly useful in returning pointers into a large data structure. For a few things this will vastly speed up code.

7) Async can now return things that are not Task. Creating things using these is not going to happen a lot, but calling things defined with them probably will.

8) You can now use expression bodies (=> definitions) in accessors, constructors, and finalizers. Some people love these...I just find them a weird syntactic sugar.

9) Throw from the middle of an expression. Okay fine. There might be a day where I find this useful...but it doesn't seem likely right now.

No comments :

Post a Comment