Inheriting from a class is a powerful mechanism, but the real inheritance power comes from an interface. An interface provides the members that a class which inherits from an interface must implement.

We can look at the interface as a contract which states that a class that implements an interface must implement all the members from it.

If you want to see complete navigation of this tutorial, you can do that here C# Intermediate Tutorial.

To download the source code, you can visit Interfaces in C# Source Code. 

We are going to split this article into the following sections:

Defining an Interface

To define an interface we need to use the interface keyword. It is quite similar to defining a class just we use another keyword. Inside that interface, we specify our members without access modifier and implementation. So, we just provide a declaration for members, an implementation is a job for a class which implements that interface:

Implementing an Interface

To implement an interface, we declare a class or structure that inherits from the interface and implements all the members from it:

Let’s see all of this through the example:

As we can see, after our classes inherit from an interface, they must implement the member WriteFile(). Otherwise, we would get a compiler error.

When we implement an interface, we must ensure to provide method implementation by following this rules:

  • The method names and return types must match exactly
  • Any parameters must match exactly
  • All the methods must be public during implementation. This is only not the case with the explicit interface implementation(we will talk about that a little later)

A class can inherit from a class and implement an interface at the same time. But if this is a case, we must specify a base class first and then an interface comma separated:

Referencing Classes Through Interfaces

In the same way that we can reference an object by using a class variable, we can define an object by using an interface variable:

As we can see, all the methods are available through the writer object. But let’s now use an interface object for referencing action:

If we use an interface to create an object, we can access only those members declared in that interface.

As we mentioned above, the interface provides a contract for the class that inherits from it. And this is a great advantage of using interfaces, we can always be sure when a class inherits from our interface it will implement all of its members.

But the interface implementation has even more advantages. One of them is object decoupling.

Using an Interface to Decouple Classes

When one class depends on another class those classes are coupled. This is something we want to avoid because if something changes in class A and Class B depends heavily on Class A, there is a great possibility that we would have to change a Class B as well. Or at least, we won’t be sure if Class B still works properly. Consequently, we want our classes to be loosely coupled or “decoupled”.

Let’s see what would happen if we create our classes as strongly coupled:

This XmlFileWriter is a class which has a purpose of writing to an xml file. Now we can instantiate our XmlWriter class, send the object through the XmlFileWriter constructor and call the Write method:

 

Ok, everything works great for now.

But we have a couple of problems here. Our XmlFileWriter class is strongly coupled to the XmlWriter class. If we change the WriteFile method inside the XmlWriter class, we must change it in the XmlFileWriter class as well. So, the change in one class leads to change in another. That’s not how we want our code to work.

Another thing. We surely want to have the same behavior for our JsonWriter class. We can’t use this XmlFileWriter (because it accepts only the XmlWriter object), we must create another class and repeat all of our actions. This is pretty bad as well.

Finally, we can ask ourselves, if we really need two classes for the same job. Why can’t we use just one? Well, that’s where interfaces come in.

Let’s modify the XmlFileWriter class:

Excellent. This is so much better.

Now our class name tells us that this class doesn’t write only xml files. Furthermore, we are not restricting our constructor to accept just XmlWiter class, but all the classes that inherit from the IWriter interface. Our method WriteFile can’t be renamed now because of our interface IWritter, which states that all classes must implement a method with an identical name. We can see now that FileWriter class are decoupled from the XmlWriter or from the JsonWriter, and that we can send objects of both classes to the FileWriter class:

Decoupled objects - Interfaces in C#

Isn’t this so much better?

Now we have one class that does its job for any class that inherits from the IWriter interface.

This feature is well known as a Dependency Injection.

Working with Multiple Interfaces

A class can inherit just from one base class, but it can implement multiple interfaces. The class must implement all the methods defined in those interfaces:

Explicit Interface Implementation

As we already said, a class can implement more than one interface. It’s not unusual that two of those interfaces have a method with the same name, but we still need to implement them in our class. To do that we do not implement a method as we did before, but we need to state the name of the interface first and then the name of a method with parameters:

As we can see, we are not using an access modifier in the method implementation.

Conclusion

In this article, we have learned:

  • How to define and implement an interface
  • How to reference a class through the interface
  • The way to decouple our objects with interfaces and dependency injection
  • To explicitly implement our interfaces

In the next article, we are going to talk about Abstract Classes in C#.

If you have enjoyed reading this article and if you would like to receive the notifications about the freshly published .NET Core content we encourage you to subscribe to our blog.