In this article, let’s have a look at the default interface methods feature which has been added in C# 8.
Scenario of Evolving Interfaces
Let’s take a scenario to understand the concept of evolving interfaces.
Let’s say we define an interface IPlayMusic
which defines two methods – Play()
and Stop()
.
Then this interface was distributed to multiple applications, which provided their application specific concrete implementation for this interface.
Now those applications are running on production. And as the owner of interface IPlayMusic
, I decide to add another method, Pause()
in the interface.
If I directly add the method to interface, it would certainly break the existing implementations – because the concrete implementation should be provided for all methods in the interface.
So, how can we solve this problem ?
Traditional Options
There are few options for making the above scenario work.
Versioning
First option is obviously to define another interface for the new method (e.g. let’s say IPlayMusicV1, IPlayMusicV2, etc). As the existing code is using old interface, it would still keep working.
But there is a disadvantage in this case. There would be a lot of versions of the same interface and then after sufficiently long time, it would be difficult to maintain them.
Inheritance
Another option is to define hierarchy of interfaces. So the application has first version interface and it will server as a base interface for the next version. As the existing implementations are using the base interface, they would not know about new methods added in derived interface. Thus they would keep working.
This option solves some basic issues like related methods are now in an hierarchy so maintaining code is bit easier than first option. This option still would need to cleanup the hierarchy of interfaces at some point in future.
Default Interface Methods
The concept in default method is simple. If a new method needs to be added to an existing interface without breaking its existing concrete implementations, then provide the default implementation. That way the existing code would still keep running.
The default implementation can be anything, it can raise NotImplementedException, or it can write something in the logs, or something else, which would allow existing application to continue work without any disruptions to its functionality.
Let’s have a look at example.
Are abstract classes in C# obsolete?
In my opinion, now the line between abstract classes and interfaces is getting blurred because of such features. It was one of the favorite topic in technical discussions to discuss about when to use interfaces and when to use abstract classes. But starting from C# 8, both are appearing to be very similar.
Let’s quickly have look at few comparison points:
Common Logic Implementation
Abstract classes can contain common logic, which would be shared across multiple concrete implementations of the abstract class. Before C# 8, this was major difference between abstract classes and interfaces.
Now, with this new feature of default implementation in interfaces, interfaces can have default implementation for the methods.
So it seems there is not difference now from this perspective.
Multiple Inheritance Support
C# (yet) does not completely support multiple inheritance. A class can not be derived from two other classes, but it can be derived from any number of interfaces.
So, technically, we can achieve multiple inheritance now as interfaces can contain default implementation.
Access Modifiers
One of the major difference between abstract classes and interfaces was – all methods declared inside an interface are by default assigned with public modifier.
But this is not true anymore. We can specify any access modifier for the method in interface as shown in above example.
Wrapping Up
Do you like this new feature ?
Well our thoughts may depend on the domain of applications we develop. This change might be good for some big applications or framework, but the medium sized applications / small applications might not want to use this feature.
Of course, this is my opinion and if you are using C# 8 or above, the language compiler would not stop you from using it. What do you think ? Let me know your thoughts.