Default implementations in interfaces

Mads Torgersen

Mads

Default implementations in interfaces

With last week’s posts Announcing .NET Core 3.0 Preview 5 and Visual Studio 2019 version 16.1 Preview 3, the last major feature of C# 8.0 is now available in preview.

A big impediment to software evolution has been the fact that you couldn’t add new members to a public interface. You would break existing implementers of the interface; after all they would have no implementation for the new member!

Default implementations help with that. An interface member can now be specified with a code body, and if an implementing class or struct does not provide an implementation of that member, no error occurs. Instead, the default implementation is used.

Let’s say that we offer the following interface:

An existing class, maybe in a different code base with different owners, implements ILogger:

Now we want to add another overload of the Log method to the interface. We can do that without breaking the existing implementation by providing a default implementation – a method body:

The ConsoleLogger still satisfies the contract provided by the interface: if it is converted to the interface and the new Log method is called it will work just fine: the interface’s default implementation is just called:

Of course an implementing class that does know about the new member is free to implement it in its own way. In that case, the default implementation is just ignored.

The best way to get acquainted with default implementations is the Tutorial: Update interfaces with default interface members in C# 8 on Microsoft Docs.

Happy hacking!

Mads

Mads Torgersen
Mads Torgersen

C# Lead Designer, .NET Team

Follow Mads   

50 Comments
Avatar
cheong00 2019-05-14 20:59:28
Does it mean we can now define private member in interfaces? That's because as far as I understands, the default implementation would still required to use defined member of the interface only, and IMO in the most cases, useful default implementation would need access to some private members. (This is the primary reason why we choose base classes over interface when need to choose between them)
Avatar
cheong00 2019-05-14 21:12:12
For some reason, I hope you can find it worth considering to allow interfaces to specify base class for default implementations. That base class could be abstract class that provides implementation for methods that it want to provide, and for members which the class wouldn't provide default implmentation it can just specify them as abstract members. In this way we can somehow solve the "multiple base class" problem - either need to explicitly cast to interface when ambiguity is found, or find some way to define proper resolve order of interface.
Avatar
Hzj_jie 何子杰 2019-05-14 23:22:53
"Oracle did this" is not a reasonable argument of doing the same thing in .net. I'd prefer to call it a horrible and easy-to-be-abused feature.
Neil Walker
Neil Walker 2019-05-15 00:19:37
When you over engineer something it doesn't get better, it starts to become a mess. There's a reason why it's an interface, if your want code, user an abstract class.  You're re just trying to fix an edge case by ruining a simple principle. Just like java did with enums. 
Avatar
Xavier Poinas 2019-05-15 00:39:04
This seems quite sloppy to me. Isn't this what abstract classes are for? With those changes, what's the difference between an interface and an abstract class? The only one I see is that a class can only inherit one (abstract) class but can implement several interfaces. The restriction on having only one base class was to avoid the typical issues associated with multiple inheritance. With interfaces behaving like classes aren't we back to multiple inheritance?
Avatar
Rehan Saeed 2019-05-15 01:00:19
This is the one feature of C# 8 that I don't like and I think is a mistake.
Avatar
Charles Roddie 2019-05-15 01:46:18
People worry that this will lead to clean code resulting from multiple inheritance. In that case it may be better to give a warning on creation of these interfaces, which can be disabled when writing Java interop code. (It is said that the real reason for this feature is Java interop. )
gekk RK
gekk RK 2019-05-15 02:09:33
And how to solve diamond inheritance problem?
Avatar
Mohamed Elshawaf 2019-05-15 05:40:37
Great to see this finally in C#!  Side question: does anyone know what JavaScript plugin is used for the code snippets in this post? 
Avatar
Yves Goergen 2019-05-15 05:56:21
Does this require changes to the .NET assembly file format? I.e. will post-compilation tools have to be updated to support this feature? From my past experience working with APIs like Cecil, I don't see how this feature would have been possible before.
Michel Renaud
Michel Renaud 2019-05-15 07:37:38
My first impression is that nothing good can come out of this feature.
Avatar
Sam 2019-05-15 09:04:16
Thanks for the blog post, Mads. Can I suggest that you make it a little more meaty and talk about inheritance and such? I've read all the design notes, but most people don't.
Avatar
Sergey Nosov 2019-05-15 10:46:41
Relax everybody, it is not too bad. There is actually no inheritance happening when a class implements an interface. I, personally, would love me some multiple inheritance in C#, but this is not it. Think of this like of explicit interface implementations. Some consider explicit interface implementations hacky as it is; so it just adds to the hackiness in the same direction.
Avatar
anonymous 2019-05-15 21:56:07
This comment has been deleted.
Avatar
Ladislav Burkovsky 2019-05-16 00:37:45
I wish we had extend everything "feature" instead.
Avatar
Иван Архипов 2019-05-16 02:40:01
I very much hope that this will never happen. The most important task of interfaces is to declare their behavior by design. And now it turns out that there is both a default implementation and an implementation that can be changed in the interface implementation. It turns out the bomb.
Nicholas Kinney
Nicholas Kinney 2019-05-16 04:46:10
 I will try my hardest to be positive here. I’ve spent the last 15 years realizing that separation of concerns and polymorphism and encapsulation and abstraction is more important than you. You are wrong, sir. But I have an open mind and would love to see how late binding contracts without implementing would improve software and improve readability. Lambda is a powerful feature but you are taking inversion of control and spawning a new version of DLL hell without even knowing it. So much for SOLID principles to say the least. Don’t know how to dispose a object, no problem our object methods are static and singletons will live in infamy by our triple locking helix magic sauce in C#11!!!!!!! Lol...
Avatar
Matthew Adams 2019-05-16 06:28:48
This change essentially enables you to use trait-based development.  Nice.
Antony McKane
Antony McKane 2019-05-16 09:22:51
This is just plain horrible.  It pointlessly blurs the line between interface and abstract base classes.  Keep interfaces as simple contracts of functionality and override functionality via derived classes. 
Avatar
jiaming hu 2019-06-03 20:33:27
I have a question about c# grammar, can I try to give feedback? But I can't find a website about the discussion. Let me talk about it directly here? if (name == null){    throw new ArgumentNullException(nameof(name));} // Can you develop a grammar like this?name ?? throw new ArgumentNullException(nameof(name)); There may be thousands of such judgments in the project, and then an exception is thrown. Can it be extracted into a single code to do it?
Andrea Rossini
Andrea Rossini 2019-06-05 01:00:01
Multiple inheritance? Is it you?
Avatar
Maciej Pilichowski 2019-06-06 05:30:30
Without private methods in interface it has little or no use IMHO, because in this example extension would be sufficient. Pity it is the last major feature -- I still wait for types unions and intersections :-)
Aaron Hudon
Aaron Hudon 2019-06-17 15:01:30
Seems like a multiple-inheritance mess waiting to happen.Is this Jon Skeet approved?
Avatar
Saeid Babaei 2019-07-06 04:30:52
I don't like that. It seems over engineering.