Introduction
If anyone asks "What is interface in C#?" then mostly our answer would be "Interface has only method declaration, not a definition and interface has only public access modifiers". But it changed after C# 8.0 has arrived. C# 8.0 introduces a new feature called "Default implementations in interfaces" and this will change many things. In this article, we are going to see about “Default implementations in interfaces” in C#.
What are "Default implementations in interfaces"?
Before going to see about this feature, let's see the legacy definition of the interface in C#.
- An interface only has declarations of methods, properties, indexers, and events.
- An interface has only public members and it cannot include private, protected, or internal members.
- An interface cannot contain fields.
By default, all the members of an interface are public and abstract.
interface ICar {
string Color { get; set; }
void Start();
void Move();
void Stop();
}
Let's consider the above ICar interface and it is implemented in many classes like Tata, Hyundai, Ford, etc in the application. But if you want to add new methods to only a few classes (not all classes which implemented this interface) then you have to do either one of the following,
You want to add new methods in the ICar interface and implement that method into all classes(some classes has an empty implementation because which are not needed in this class)
You can create an extended ICarExtended interface with a new method (this interface will inherit from the existing ICar interface) and is implemented in the necessary classes.
interface ICar {
string Color {
get;
set;
}
void Start();
void Move();
void Stop();
}
interface ICarExtended: ICar {
void EnableAutoPilotMode();
}
The second approach would be an appropriate solution for the above problem. But consider if you want to add a new method to some other few classes then, again you have to create an extended interface. If the interface list grows up, then it would be difficult to maintain code. "Default implementations in interfaces" has a solution to resolve this problem.
This feature helps us to write an implementation of any method. This is useful in situations where you can add new methods to interface with a default implementation, without breaking the existing implementation.
Consider the below interface ICar. It has method declarations which are Start(), Move() and Stop(). The EnableAutoPilotMode() method has a default definition.
interface ICar {
private static string command = "";
private void Initialize() {
command = "Default";
}
private string DefaultValue() {
return command;
}
string Color {
get;
set;
}
void Start();
void Move();
void Stop();
void EnableAutoPilotMode() {
Initialize();
Console.WriteLine("{0} - EnableAutoPilotMode", DefaultValue());
}
}
Implement the ICar interface in both TataCar and HyundaiCar classes. Here, we can override the default implementation in the classes. If any class overrides it, then its own implementation will be called. We have overridden the EnableAutoPilotMode() method's default implementation in the TataCar class and HyundaiCar has doesn't have any implementation for EnableAutoPilotMode() method.
public class TataCar: ICar {
public string Color {
get;
set;
}
public void Move() {
Console.WriteLine("Tata - Move");
}
public void Start() {
Console.WriteLine("Tata - Start");
}
public void Stop() {
Console.WriteLine("Tata - Stop");
}
public void EnableAutoPilotMode() {
Console.WriteLine("Tata - EnableAutoPilotMode");
}
}
public class HyundaiCar: ICar {
public string Color {
get;
set;
}
public void Move() {
Console.WriteLine("Hyundai - Move");
}
public void Start() {
Console.WriteLine("Hyundai - Start");
}
public void Stop() {
Console.WriteLine("Hyundai - Stop");
}
}
static void Main(string[] args) {
ICar tataCar = new TataCar();
ICar hyundaiCar = new HyundaiCar();
tataCar.Start();
tataCar.Stop();
tataCar.EnableAutoPilotMode();
Console.WriteLine("\n");
hyundaiCar.Start();
hyundaiCar.Stop();
hyundaiCar.EnableAutoPilotMode();
Console.ReadLine();
}
EnableAutoPilotMode() method in TataCar class prints the overridden value. But EnableAutoPilotMode() method in HyundaiCar prints the default value.
![]()
Interface in C# as per new feature,
- Interfaces can have the default implementation of methods.
- Interfaces can have Private members.
- Interfaces can also have protected members. They are not accessible by the derived class but can access via the derived interface.
- Interfaces can also have static members.
- Interfaces can also have virtual members, but the class can’t override this method. But can be overridden by an inherited interface.
Why do we need "Default implementations in interfaces"?
According to Microsoft,
- Default interface methods enable an API author to add methods to an interface in future versions without breaking source or binary compatibility with existing implementations of that interface.
- The feature enables C# to interoperate with APIs targeting Android (Java) and iOS (Swift), which support similar features.
- As it turns out, adding default interface implementations provides the elements of the “traits” language feature (https://en.wikipedia.org/wiki/Trait_(computer_programming)). Traits have proven to be a powerful programming technique (http://scg.unibe.ch/archive/papers/Scha03aTraits.pdf).
This "Default implementations in interfaces" is an optional feature only. If you face any problem like API compatibility then you can use this feature to avoid the issues. But this also depends on your requirement and design of the application. Still, there are mixed feedback and commands from the developer community about this feature. But everything depends on us whether this feature is good or not needed.
Summary
- The default implementation is a useful feature that allows developers to release new changes without breaking the existing implementation.
- This feature has introduced in C# 8.0.
- The Interface can have private, protected, static, and virtual members.
I hope you have liked it and know about the new features on the interface in C# 8.0.