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 virtual nor sealed are specified, we assume the member is abstract.
  • if there is an implementation and neither abstract nor sealed are specified, we assume the member is virtual .
  • sealed modifier is required to make a method neither virtual nor abstract.

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 abstract method stays abstract.
  • virtual method stays virtual .
  • a method without any modifier stays neither virtual , nor abstract.
  • sealed modifier 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.