C# 8 release date is coming closer and closer so it’s about time we start reviewing the different proposed features so we can understand what is coming and utilize it as best as possible.

So let’s start with default interface methods. This sounds really weird doesn’t it? Interfaces are there only to define a contract. A set of public methods an implementing class will have, but freedom was given to that class to implement every method in its own way. If so far we needed to also provide an implementation for one or more of those methods we would use inheritance.

If we wanted that class to not implement all methods but only a subset of them, we would make the methods and the class itself abstract.

For example we could never write the following

interface IExample { void Ex1(); // allowed void Ex2() = Console.WriteLine("IExample.Ex2"); // not allowed }

instead we would have to write the following

abstract class ExampleBase { public abstract void Ex1(); public void Ex2() = Console.WriteLine("ExampleBase.Ex2"); }

This was ok, it was more than enough to cover our needs.

The Diamond Problem

So what changed? Why do we need to introduce this new feature? What were we missing and never noticed that we were missing?

Well C# (and many other languages) does not support multiple inheritance due to the diamond problem. In order to allow multiple inheritance while avoiding the diamond problem C# 8 is introducing default interface methods.

Using default interface methods from now on you can have an interface definition and a default implementation of some or all of its methods within that definition.

interface IExample { void Ex1(); // allowed void Ex2() = Console.WriteLine("IExample.Ex2"); // allowed }

So now you can implement an interface that includes already implemented methods and you can avoid duplication of code in classes that wish to inherit from a specific class but also have common methods.

With Default Interface methods the diamond problem is not 100% solved. It might still happen a case where a single class, is implementing two interfaces that inherite from a third one and all implement the same method.

In this case the C# compiler will choose the appropriate method to call based on the current context. If it is unable to infer a specific one then a compilation error will be shown.

For example let’s say we have the following interfaces

interface IA { void DoSomething(); } interface IB : IA { void DoSomething() = Console.WriteLine("I am Interface B"); } interface IC : IA { void DoSomething() = Console.WriteLine("I am Interface C"); }

And I am creating a class that implements both of the above methods

public class D : IB, IC { }

Now if in my main code this happens:

static void Main() { var x = new D(); x.DoSomething(); }

This will throw a compilation error. The error will be that the compiler cannot infer which method to call and throws an error because no specific method was found.

On the other hand, if class D implements its own version of the DoSomething method then the compiler will know which one to call.

Other benefits

Using default interface implementations of methods an API provider can extend an interface without breaking any part of legacy code.

The Trait Pattern

The trait pattern is basically a set of methods that multiple classes needed them.

So far the trait pattern in C# was implement using Abstract classes. But with multiple inheritance not available, implementing the trait patter was becoming very tricky so most people would either avoid it, or get lost in a huge chain of inheritance.

Using default method implementations in Interfaces though this will change.

We can provide a set of methods that we need our classes to have just by using default interface method implementations in our interfaces that they will implement.

Any of the classes can override these methods with their own implementation of course, but we provide them with a default set of implementations in case they do not wish to.