What I get from the preview of C# 8 with Mads Torgersen

C# 8 will introduce some major features, who claimed tought work from the bottom.

Nullable references types

This feature is about to eliminate as much as possible the billion dollar error that we all know, the null reference exception.

The null reference exception occurred when you reference an object who can be null. For example, a string s can have a value or can be null, but even if it's null, you can call some properties like Length. You call a property or a method on a null object, so it throw a null reference exception.

C# already add stuffs to help developers dealing with this issue, like the nullable operator.

We already know this syntaxes :


int i = 0; // i can't be null
int? i2 = null; // i can be null

C# 8 will introduce the nullable operator for other types like strings, so this code sample will be correct :


string s;
string? s;

Fear not, string will conitnue to be a nullable type but you will can add a ? to tell that this variable is supposed to be null, or have much chance to be null. It's more like a design feature.

Moreover, it will allow the compiler to help you dealing with this issues. In this way, with the next situation the compiler will raise a warning to tell you "be careful, you reference something that might be null" :


string? s = null;
int i = s.Length; // Warning here from the compiler

To avoid this compiler's warning, you have just to check if the object you work with is null or not :


string? s = null;
if(s != null){ // Avoid a warning from the compiler
	int i = s.Length; // No warning here
}

Notice that you have to explicitly check if the variable is null or not, you can't use the "damnit operator" (to quote Mads Torgersen). So in the next example, the compiler won't know that you variable is not null and will raise a warning :


string? s = null;
if(!s.IsNullOrWhiteSpace()){
	int i = s.Length; // The compiler will raise a warning here
}

To avoid this warning, you can tell the compiler that you know this object is not null and that you can reference it using the "damnit operator", like this :


string? s = null;
if(!s.IsNullOrWhiteSpace()){
	int i = s!.Length; // The compiler will not raise a warning because you tell it that you know what you are doing here
}

So, let's make a summary :


string s; // this variable should never be null
string? s1; // this variable can be null

s?.Length; // you ask the compiler to check for null
s!.Length; // you tell the compiler that you know what you are doing and that s is not null. And yes, it's a lot of responsability :)

It's looks like a small feature but it's a big thing I think. With this new feature, you will can help the compiler to understand you code better, and in this way his support will be much more effective. Really ingenious stuff.

Async streams

This feature is about eliminate the callback's hell code.

You already know the syntax :


async Task<int> GetLength(){
	return 1;
}

await GetLength();

Now imagine the scenario that you develop a mobile application who gets his data from the cloud, and because it has to get a huge set of data you want to perform this in several tasks when you need it, and not get all the data in one big call then use it. In this case, the async iterator does the job :


IAsyncEnumerable<T> stream = [...]

foreach await(var s in stream)
{
	// it doesn't block the thread during you get this item
	// when the data is here, it will move next to the next one
}

Default Interface Implementations

For information, it's a feature who had an impact on the runtime, the first time for a long time the C# team and the runtime team had to work together.

This feature allow interfaces to have default implementation, so their members with default implementations doesn't must have an implementation in their children.

Assume that you have this interface and this class :


public interface INotify
{
	void Notify();
}

public class MyNotifyClass : INotify
{
	public void Notify()
	{
		// Do some stuff
	}
}

Imagine that you want to add a method on the interface without breaking the code, you can't. You will have to create another interface, and let's your class inherit later from this another interface, etc.

With the default interface implementations, you can add a method to your interface with a default implementation, and the class whom inherits from this interface will not must implement this new member as long as it has a default implementation.


public interface INotify
{
	void Notify();
	void NotifyAll() {  }
}

public class MyNotifyClass : INotify
{
	public void Notify()
	{
		// Do some stuff
	}
}

Notice that with this new feature the difference between an interface and an abstract class is become less, but there are still some differences like you can inherit from multiple interfaces but only one class.

Another interesting thing (I don't know if it's a new feature of C# 8 or it was already exist) is about the implicit member's implementation and casting. A private implementation isn't available when you call a class, but it is if you cast your class into the interface :


public interface INotify
{
	void Notify();
	void NotifyAll() {  }
}

public class MyNotifyClass : INotify
{
	public void Notify()
	{
		// Do some stuff
	}

	private void NotifyAll()
	{
		// Do some stuff
	}
}

MyNotifyClass myClass = new MyNotifyClass();
myClass.NotifyAll(); // Doesn't work because NotifyAll() is private

INotify myNotifyInterface = (INotify)myClass;
myNotifyInterface.NotifyAll(); // It works

Extension Everything

Currently, you can extends objects using static classes and static methods, like this :


public class Person
{

}

public static class Ext
{
	public static T M<T>(this Person person)
        {
            return default(T);
        }
}

But it has the limitation that you only can extend objects. You cannot extend properties, because of that : what it's the first "property" of a property ?

So the all way was reviewed and C# 8 will introduce a new syntax to declare extensions that will allow to extend everything :

The syntax is this one :


extension MyPersonExtension extends Person
{

}

It doesn't modify the type of the class who it's extended, but it's adding some stuff to it in the current assembly.


extension MyPersonExtension extends Person
{
	public int CountFingers()
	{
		this. // it call the current instance of Person
	}
}

extension MyPersonExtension extends Person
{
	public int NumberOfFingers()
	{
		get { ... }
	}
}

extension MyPersonExtension extends Person
{
	static int ... // You can add static things
}

Another feature who will not be released in C# 8.0 but maybe in a future minor release is the possibility to have extension interfaces implementations. Imagine the scenario : the developer team who wrote the Person class didn't know about the employee who it's a new feature and for a reason we don't care here, the Person class cannot be updated. With this next feature which is not done but on the radar, you will be able to do something like this :


extension MyPersonExtension extends Person : IEmployee // The Person class implements now the IEmployee interface in your assembly
{
	[ ... ]
}

Just awesome, powerful.

Watch the video

August 22, 2017
  • C#
  • Csharp
  • C# 8.0
  • C# 8
  • Channel9