You already know that interfaces are meant to be immutable and should not be upgraded once released. Before C# 8.0, the best way to extend an interface was to create extension classes for adding default behaviors. But with default interface methods, you can skip the extension class implementation and implement methods within the interface itself without breaking any existing implementations.
Let’s imagine this scenario: You’re maintaining accounting software for a big bank where you have a simple interface (like below) representing a bank account. There are a few existing implementations of the interface e.g. CheckingAccount, SavingsAccount, and so on.
New requirements that have a far-reaching impact
A few years down the road, there may be some new requirements for the IBankAccount interface around easing some repetitive code that your client has to write all over the application. More specifically, these would be convenience methods for existing implementations. You obviously don’t want to change the interface, as there may be a large user base still using it. Before C# 8.0, you would create an extension class for the IBankAccount interface that looks something like this:
Activating the default interface methods in C# 8
With C# 8.0, the default implementations of the above extension methods can be easily moved into the interface without breaking existing implementations using the default interface methods. Here is how the new code would look:
This syntax is much more intuitive and concise.
Extended use cases for default interface methods
A few years more years down the road, you might get a new requirement to add a default functionality to give 2% cashback on grocery transactions, but the implementer can also choose to give cashback on multiple user-chosen categories. Let’s see what that code would look like:
Above, we’ve set the default cashback category as Groceries and added a shared method called “DefaultComputeCashBack” that calculates the cashback on transactions when the category is Groceries. However, we also provide another method called ComputeCashBack, which can be overridden by the implementer to add logic for calculating cashback on custom user-chosen categories.
The default implementation of ComputeCashBack calls the shared method as well. The implementing classes of the above interface can now choose to:
- Not override ComputeCashBack, in which case the default cashback on groceries will be computed.
- Override ComputeCashBack, check if the user has chosen a cashback category, and based on that, use a mix of shared method and custom calculation logic. Here’s what that would look like:
Thus, with the new feature, you can not only eliminate the need to implement extension classes where possible, but also add upgrades to your interfaces when new requirements are discovered for the same functional idea.
So what are the key things you need to know about default interfaces?
- If you are on .NET Core 3.0, use default interface methods in place of extension classes. The syntax is much more intuitive and concise.
- When requirements demand having a default functionality on an interface, irrespective of the implementations, consider using static methods on the interface itself with the required functionality.