Kenneth Truyers

New features in C# 7, part 2

Introduction

Kenneth Truyers

Kenneth Truyers


.NET c#

New features in C# 7, part 2

Posted by Kenneth Truyers on .
Featured

.NET c#

New features in C# 7, part 2

Posted by Kenneth Truyers on .

In my previous post about probable new features in C# 7, I talked about Tuples, Record Types and Pattern Matching. These are the most obvious candidates for inclusion. In this post I want to highlight a few more new features that are not getting as much attention but are also very useful features.

C# 7 Non-nullable reference types

What?

Nullable value types where introduced in C# 2.0. Essentially they’re just syntactic sugar around the Nullable 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

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 calculations 
    return Factorial(input); 
}

C# 7 Immutable Types

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
  • Reference 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. 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

As I said before, it’s still early days, so the above syntax can (and probably will) change, but these features are very exciting and will make C# even more enjoyable to work with. I encourage everyone to have a look on GitHub to follow the current discussions around these features:

Work List of Features

The full details of the above proposals can also be found here:

Non-nullable reference types
Local functions
Immutable types

Kenneth Truyers

Kenneth Truyers

View Comments...