
Nov 06, 20206 min read
C# 8 new default interface methods
The default interface method is very useful, which allows the developer to release new changes in any interface as it progresses without breaking anything. As usual, t…
If someone asks me “Can we have access modifiers in C# interface”, my answer would be obviously “Hell NO “.
From the beginning, as far as I know, it was impossible to implement any type (with access modifier private, protected, or internal) of members in the interface, nor it contains any field.
By default, the obvious reason was that interfaces are public and abstract, and inheriting classes must provide the implementation. Thus we were allowed only to implement methods declaration.
Finally, moving forwared the interview question becomes pretty much irrelevent for the next generation to come.
With C# 8, Things are changes, now we can have a default implementation of methods in an interface as well as interface members can be private, protected, internal or static.
Let’s talk about the “Default implementation”, and what benefit it brings with it.
Earlier we used to have interface implemented in a number of classes. If we need a new member we used to:
- Eiter we update all the classes to support the new member.
- Or we extend the interface with new method/member and inherit with exiting interface
interface ICar
{
void GetSpeed();
void GetMilage();
}
interface IAutonomousCar: ICar
{
void SendCommand();
}I guess we all know where we ended up with such implementation. The list of extended interfaces grows till it becomes unmanageable.
C# 8 answers to this by introducing “Default implementation in interfaces” which adds support for virtual extension methods – methods in interface with a concrete implementation.
Concrete methods in interfaces
We can now add members to interface and provide an implementation for those members. This feature enables an API author to add methods to an interface in a future version without breaking source or library with the existing implementation. Very much like Java’s “Default Methods“.
By the way, this feature requires support in the CLI/CLR and programmes that take advantage of this feature cannot run on earlier versions of the platform.
Following class implements this interface need not implement its concrete method:
interface ICar
{
void GetSpeed();
void GetMilage();
void SendCommand()
{
Console.WriteLine("Command Send via Interface");
}
}
class ToyotaGarage : ICar
{
public void GetSpeed()
{
Console.WriteLine("200 KMPH");
}
public void GetMilage()
{
Console.WriteLine("10 KM Per Liter");
}
}We did not implement SendCommand method into the class
ToyotaGarage. However, the default implementation will be available from an instance of the interface:
class Program
{
static void Main(string[] args)
{
ICar tg = new ToyotaGarage();
tg.SendComand(); // prints "Command Send via Interface"
}
}C# 8 now allow us to override a concrete method of the interface in the inherited class. :
class TeslaGarage : ICar
{
public void GetSpeed()
{
Console.WriteLine("350 KMPH");
}
public void GetMilage()
{
Console.WriteLine("50 KM Per Charge")
}
override void SendCommand()
{
Console.WriteLine("Command Send via TeslaGarage");
}
}In this example, TeslaGarage simply override the concrete method SendCommandof the interface.
Overrides in interfaces
The override statement allows us to provide the most specific implementation of a virtual member in the interface, where the member will not be found by the compiler or runtime. It also allows turning an abstract member from a super-interface into a default member in a derived interface.
In simple a derived interface can provide a more appropriate default implementation by explicitly implementing the base member:
> _Override declaration in interfaces may not be declared sealed._
interface IA
{
void M() { WriteLine("IA.M"); }
}
interface IB : IA
{
override void IA.M() { WriteLine("IB.M"); } // explicitly named
}
interface IC : IA
{
override void M() { WriteLine("IC.M"); } // implicitly named
}We explicitly implement the base member by including IA. in the name. Without IA., the compiler would warn us to either make it explicit or use the new keyword if we want to hide it.
Modifiers in interfaces
C# 8 now support modifiers on its members such as : private, protected, internal, public, virtual, abstract, sealed, static, extern, and partial.
Internal members only can be accessed through the derived interface
An interface member with a concrete method is by default a virtual member unless explicitly sealed or private modified are used. virtual members cant be overridden by class, the only derived interfaces can override it:
public interface ICar
{
public virtual void SendCommand()
{
Console.WriteLine("Command Sent via Interface");
}
}
public interface IAnotherCar :ICar
{
void ICar.SendCommand()
{
Console.WriteLine("Command Sent via another Interface");
}
}
class MorrisGarage: ICar, IAnotherCar
{
}
class Program
{
static void Main()
{
ICar mg= new MorrisGarage();
mg.SendCommand(); //Calls the virtual implementation.
IAnotherCar mgOverridden = new MorrisGarage();
mgOverridden.SendCommand(); //Calls the overridden implementation.
}
}Virtual Modifier vs sealed Modifier (Source)
It is allowed that modifiers to be stated on interface members unless there is a reason to disallow some of them. This brings an interesting question around virtual modifier. Should it be required on members with default implementation?
We could say that:
- if there is no implementation and neither
virtualnorsealedare specified, we assume the member isabstract. - if there is an implementation and neither
abstractnorsealedare specified, we assume the member isvirtual. sealedmodifier is required to make a method neithervirtualnorabstract.
Alternatively, we could say that virtual modifier is required for a virtual member. I.e, if there is a member with implementation not explicitly marked with virtual modifier, it is neither virtual, nor abstract. This approach might provide a better experience when a method is moved from a class to an interface:
- an
abstractmethod staysabstract. - a
virtualmethod staysvirtual. - a method without any modifier stays neither
virtual, norabstract. sealedmodifier cannot be applied to a method that is not an override.
What do you think? comment below
Similar can be applied on abstract modifier, although
abstract is a default on all members (without body or concrete method) of the interface, that modifier may be given explicitly. Although every class need to implement the interface methods.
protected members are not accessible by derived class but via the derived interface. If a class requires to implement protected member, this has to be done through interface explicitly:
public interface ICar
{
public void SendCommand()
{
Console.WriteLine("Command Sent via Interface");
}
protected void SendCriticalCommand()
{
Console.WriteLine("Critical Command Sent via Interface");
}
}
public interface IAnotherCar : ICar
{
public void Send(bool bCritical)
{
if (bCritical)
this.SendCriticalCommand();
else
Console.WriteLine("Command Sent via Morris Garage Class");
}
}Last but not least, the interface can declare a
static member, including nested types, methods, properties event and static constructors.
CLR support API
In order for compilers to detect when they are compiling for a runtime that supports this feature, libraries for such runtimes are modified to advertise that fact through the API discussed in https://github.com/dotnet/corefx/issues/17116. As it add:
namespace System.Runtime.CompilerServices
{
public static class RuntimeFeature
{
// Presence of the field indicates runtime support
public const string DefaultInterfaceImplementation = nameof(DefaultInterfaceImplementation);
}
}Abstract classes vs. interfaces in C# 8.0
Now the question arises if abstract classes and interfaces are the same in new C#? Although they are very similar in more ways than one, there are subtle differences between the two. We cannot extend a class and unlike an abstract class, the interface can not have instance members and you still can implement several interfaces.
Conclusion
The default interface method is very useful, which allows the developer to release new changes in any interface as it progresses without breaking anything.
As usual, this received mix feedback but I am thrilled and believe it is moving forward. Java and Scala already have this feature which enables C# to interoperate with APIs targeting Android (Java) and iOS (Swift), which support similar features.
This feature is taking C# into the direction from Oops to functional programming. As it turns out, adding default interface implementations provides the elements of the “traits” language features. Traits have proven to be a powerful programming technique.
Related posts

Best Practices for Designing C# Classes and Interfaces
In this blog post, we will discuss best practices for designing C classes and interfaces. We will cover important topics such as naming conventions, encapsulation, inh…

Best Practices for Error Handling in C# Applications
Are you working on a C project that requires concurrency? Writing thread-safe code is crucial to ensure that your application works as intended, without the risk of ra…

Unlocking the Power of C# Concurrency: Proven Tips and Tricks
Are you working on a C project that requires concurrency? Writing thread-safe code is crucial to ensure that your application works as intended, without the risk of ra…