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

C# 8 will introduce some major features, which required tough work from the ground up.

Nullable reference types

This feature is about eliminating as much as possible the billion dollar mistake that we all know, the null reference exception.

The null reference exception occurs when you reference an object that 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 throws a null reference exception.

C# has already added things to help developers deal with this issue, like the nullable operator.

We already know these 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 continue to be a nullable type but you will be able to add a ? to tell that this variable is supposed to be null, or is likely to be null. It's more like a design feature.

Moreover, it will allow the compiler to help you deal with these issues. This way, in the following 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 warning, you just have to check whether 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 whether 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 your 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 summarize:


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 looks like a small feature but I think it's a big thing. With this new feature, you will be able to help the compiler understand your code better, and this way its support will be much more effective. Really ingenious stuff.

Async streams

This feature is about eliminating callback hell.

You already know the syntax:


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

await GetLength();

Now imagine the scenario where you develop a mobile application that gets its data from the cloud, and because it has to get a huge set of data you want to do this in several tasks when you need it, instead of getting all the data in one big call and then using 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 your information, it's a feature that had an impact on the runtime; for the first time in a long time, the C# team and the runtime team had to work together.

This feature allows interfaces to have default implementations, so their members with default implementations don't have to be implemented 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 to the interface without breaking the code: you can't. You will have to create another interface, and then let your class inherit from that other interface, and so on.

With default interface implementations, you can add a method to your interface with a default implementation, and the class that inherits from this interface will not have to 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 becomes smaller, but there are still some differences, like the fact that 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 if it already existed) is about implicit member implementation and casting. A private implementation isn't available when you call a class, but it is if you cast your class to 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 extend 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 can only extend objects. You cannot extend properties, because of this: what is the first "property" of a property?

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

The syntax is this one:


extension MyPersonExtension extends Person
{

}

It doesn't modify the type of the class that is extended, but it adds 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 that will not be released in C# 8.0 but maybe in a future minor release is the possibility to have extension interface implementations. Imagine the scenario: the developer team that wrote the Person class didn't know about the employee, which is a new feature, and for a reason we don't care about here, the Person class cannot be updated. With this next feature, which is not done but is 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