C# 7: New Features

C# 7 It seems like only yesterday we got C# 6, but as it goes in software development land, the next thing is already on its way. In this post I want to describe the most likely new C# 7 features, what they look like and why they’re useful.

C# 7 Tuples

Update 22/07/2016: Tuples are planned to be a part of C# 7

What?

Tuples are a temporary grouping of values. You could compare a Tuple to a POCO-class, but instead of defining it as a class you can define it on the fly. The following is an example of such a class:

class PropertyBag
{
    public int Id {get; set;}
    public string Name {get; set;}
}
var myObj = new PropertyBag { Id = 1, Name = "test};

In the above example it wasn’t really necessary to name the concept we’re working with as it is probably a temporary structure that doesn’t need naming. Tuples are a way of temporarily creating such structures on the fly without the need to create classes

Why?

The most common reason for having a group of values temporarily grouped are multiple return values from a method. Currently, there are a few ways of doing that in C#:

Out parameters

public void GetLatLng(string address, out double lat, out double lng) { ... }

double lat, lng;
GetLatLng(myValues, out lat, out lng);
Console.WriteLine($"Lat: {lat}, Long: {lng}"); 

Using out-parameters has several disadvantages:

  • It cannot be used for async-methods
  • You have to declare the parameters upfront (and you can’t use var, you have to include the type)

Tuple-type

There currently already is a Tuple-type in C# that behaves like a native tuple. You could rewrite the previous method as follows:

public Tuple<int, int> GetLatLng(string address) { ... }

var latLng = GetLatLng("some address");
Console.WriteLine($"Lat: {latLng.Item1}, Long: {latLng.Item2}"); 

This does not have the disadvantages of out-parameters, but the resulting code is rather obscure with the resulting tuple having property names like Item1 and Item2.

Class / struct

You could also declare a new type and use that as the return type:

struct LatLng{ public double Lat; public double Lng;}
public LatLng GetLatLng(string address) { ... }

var ll= GetLatLng("some address");
Console.WriteLine($"Lat: {ll.Lat}, Long: {ll.Lng}"); 

This has none of the disadvantages of out-parameters and the tuple type, but it’s rather verbose and it is meaningless overhead.

How?

There are a few different use cases for tuples that will be available with C# 7 Tuples:

Tuple return types

You can specify multiple return types for a function, in much the same syntax as you do for specifying multiple input types (method arguments)

public (double lat, double lng) GetLatLng(string address) { ... }

var ll = GetLatLng("some address"); 
Console.WriteLine($"Lat: {ll.lat}, Long: {ll.lng}");

Inline tuples

You could also create tuples inline:

var ll = new (double lat, double lng) { lat = 0, lng = 0 };

Tuple deconstruction

Because the bundling of the values is not important as a concept, it’s quite possible that you don’t want to access the bundle at all, but get straight to the internal values. Instead of accessing the tuple properties as in the example of Tuple Return Types, you can also destructure the tuple immediately:

(var lat, var lng) = GetLatLng("some address");
Console.WriteLine($"Lat: {lat}, Long: {lng}");

C# 7 Record types

Update 22/07/2016: Records are probably not coming in C# 7, but will have to wait until the next version (supposedly c# 8)

What?

A record type is a simple bag of properties, a data type with only properties

Why?

Often classes or structs are merely a collection of properties. They still need a full declaration which is quite verbose. The following class demonstrates that a class with 3 properties requires quite a bit of text to declare:

class MyPoint
{
    int _x;
    int _y;
    int _z;
    MyPoint(int x, int y, int z){
        this._x = x;
        this._y = y;
        this._z = z;
    }
    public int X {get{ return this._x;}}
    public int Y {get{ return this._y;}}
    public int Z {get{ return this._z;}}
}

How?

With record types you could write the above in a single line:

class Point(int X, int Y, int Z);

You will get a few more things out of this:

  • The class will automatically implement IEquatable<Point>, which means you can compare two record types based on their values instead of reference.
  • The ToString-method will output the values in the record

C# 7 Pattern Matching

Update 22/07/2016: Pattern matching is planned to be partially supported in C# 7. In C# 7 only switching on types will be available. Full support for pattern matching will come in the next version (supposedly c# 8)

What?

With record types in play, we can now get pattern matching built-in. Pattern matching means that you can switch on the type of data you have to execute one or the other statement.

Why?

Although pattern matching looks a lot like if/else, it has certain advantages:

  • You can do pattern matching on any data type, even your own, whereas if/else you always need primitives to match
  • Pattern matching can extract values from your expression

How?

The following is an example of pattern matching:

class Geometry();
class Triangle(int Width, int Height, int Base) : Geometry;
class Rectangle(int Width, int Height) : Geometry;
class Square(int width) : Geometry;

Geometry g = new Square(5);
switch (g)
{
    case Triangle(int Width, int Height, int Base):
        WriteLine($"{Width} {Height} {Base}");
        break;
    case Rectangle(int Width, int Height):
        WriteLine($"{Width} {Height}");
        break;
    case Square(int Width):
        WriteLine($"{Width}");
        break;
    default:
        WriteLine("<other>");
        break;
}

In the sample above you can see how we match on the data type and immediately destructure it into its components.

C# 7 Non-nullable reference types

Update 22/07/2016: Non-nullable reference types are probably not coming in C# 7, but will have to wait until the next version (supposedly c# 8)

What?

Nullable value types where introduced in C# 2.0. Essentially they’re just syntactic sugar around the Nullable<T> class. Non-nullable reference types are the reverse of that feature. It let’s you declare a reference type that is guaranteed not to be null.

Why?

The null reference has been called “The billion dollar mistake” (by the inventor: Tony Hoare). NullReference exceptions are all too common. The problem is two-fold: either you don’t check for them and then you might get runtime exceptions or you do check for them and then your code becomes verbose or littered with statements that have little to do with what you’re actually trying to achieve. The ability to declare a reference type as non-nullable overcomes these problems.

How?

NOTE: The syntax here is still in flux and will probably change. There are various proposals floating around and it’s still unclear what the definitive form will be. Also, where I mention “error”, it’s still unclear whether it will be a compilation error or just a warning.

First of all, the ideal syntax would be to default to non-nullable reference types. This would provide symmetry between reference and value types:

int a;     //non-nullable value type
int? b;    //nullable value type
string c;  //non-nullable reference type
string? d; //nullable reference type

However, there are millions of lines of C# out there that would break if non-nullable types would become the default, so unfortunately it has to be designed differently to keep everything backwards compatible. The currently proposed syntax is as follows:

int a;     //non-nullable value type
int? b;    //nullable value type
string! c; //non-nullable reference type
string d;  //nullable reference type

Using nullable and non-nullable types will then affect the compiler:

MyClass a;  // Nullable reference type
MyClass! b; // Non-nullable reference type

a = null;   // OK, this is nullable
b = null;   // Error, b is non-nullable
b = a;      // Error, n might be null, s can't be null

WriteLine(b.ToString()); // OK, can't be null
WriteLine(a.ToString()); // Warning! Could be null!

if (a != null) { WriteLine(a.ToString); } // OK, you checked
WriteLine(a!.Length); // Ok, if you say so

Using this syntax is OK, but it would become problematic for generic types:

// The Dictionary is non-nullable but string, List and MyClass aren't

Dictionary<string, List<MyClass>>! myDict; // Proper way to declare all types as non-nullable Dictionary<string!, List<MyClass!>!>! myDict;

The above is a bit difficult to read (and type) so a shortcut has also been proposed:

// Typing ! in front of the type arguments makes all types non-nullable
Dictionary!<string, List<MyClass>> myDict;

C# 7 Local Functions

Update 22/07/2016: Local functions are planned to be a part of C# 7

What?

The ability to declare methods and types in block scope.

Why?

This is already (kind of) possible by using the Func and Action types with anonymous methods. However, they lack a few features:

  • Generics
  • ref and out parameters
  • params

Local functions would have the same capabilities as normal methods but would only be scoped to the block they were declared in.

How?

public int Calculate(int someInput)
{
    int Factorial(int i)
    {
        if (i <= 1)
            return 1;
        return i * Factorial(i - 1);
    }
    var input = someInput + ... // Other calcs

    return Factorial(input);
}

C# 7 Immutable Types

Update 22/07/2016: Immutable types are currently not on the planning for C# 7, nor the next version

What?

An immutable object is an object whose state cannot be modified after its creation.

Why?

Immutable objects are offer a few benefits:

  • Inherently thread-safe
  • Makes it easier to use and reason about code
  • Easier to parallelize your code
  • References to immutable objects can be cached, as they won’t change

Currently it’s already possible to declare immutable objects:

public class Point
{
    public Point(int x, int y)
    {
        x = x;
        Y = y;
    }

    public int X { get; }
    public int Y { get; }
}

While the above is definitely an immutable object, the problem is that the intent is not clearly visible. One day, someone might add a setter and consumers of this type, expecting immutability, could experience different results.

How?

NOTE: Again, the syntax here is still in flux but the initial proposal suggests adding an immutable keyword:

public immutable class Point
{
    public Point(int x, int y)
    {
        x = x;
        Y = y;
    }

    public int X { get; }
    public int Y { get; }
}

When you have immutable types, a nice addition is language support for creating new instances based on a different instance:

var a = new Point(2, 5);
var b = a with { X = 1};

Conclusion

For more information about these and other new proposed features, head over to GitHub for the full list:

Work List of Features

NOTE: It’s still early days, the syntax of all of these can (and probably will) change. Some features might not even make it into C# 7 so we’ll have to wait until C# 8 or later. I encourage everyone to take a look on the GitHub page to examine and learn about these features. The discussion is quite lively there. If you have another good proposal, check out the same forums and maybe your feature gets the cut. It’s really nice that Microsoft has opened up all these channels, so we better make use of them!

Update 22/07/2016 If you want to try out these features, you can now download the preview version of Visual Studio “15” Preview 3 (which is different from Visual Studio 2015).

Comments are closed.