This article describes the use of the interface construct in C#. Using interfaces is an important part of developing flexible software. An interface provides indirection between communicating classes. Indirection because the client class, using a service provided in another class, does not have to know anything about the service class except that it is implementing an interface. The client class can use a service provided by any class implementing the required interface.

Introduction

This article shows the benefits that can be obtained when deriving from interfaces in .NET.

To speak the same language it is important that we understand what an interface is since the word interface has a different meaning based on the context it is used in. The word interface is often used to describe the public parts of a class, i.e. the part that can be seen from others classes. The graphical user interface (GUI) is another use of the word interface. This article will describe the C# interface construct.

An interface is a construction similar to an abstract class but with no implementation code. That is, an interface is only composed of method declarations, indexers, events and constants. This article only deals with method declarations. An interface can be used anywhere in the class design as instance variables or parameters in method signatures. An interface is a contract defining that any class that implements an interface must implement all the method definitions given in the interface. An interface says what a user of the interface must do, but not how to do it. An interface defines behavioral characteristics and places those behaviors in classes independent of the class hierarchy. When a class makes a contract by applying an interface, the class is said to implement the interface or inheriting from the interface. This article uses the phrase: Implement an interface.

Example of an Interface and Implementation

There is no implementation code present, only method signatures. An implementing class must write the body code for the two methods:

It is common to use the prefix 'I' in front of an interface name, but it is not required. It makes it easier to read and understand the design illustrated whether it is a UML class diagram or a bunch of source files that you got from a third party.

Class and interface polymorphism is basically the same thing. The type (Room) of the variable (r1) and the type of the object (LivingRoom) stored in it is not exactly the same.

Room r1 = new LivingRoom()

The Room type is said to be of static type and the LivingRoom type is said to be of a dynamic type or subtype. The smart thing about using polymorphism is, among other factors, that you can wait until runtime to decide what type to use for your variable. Because of this, polymorphism is also called late binding. An interface does not have a constructor so one can only create an object of an interface as a subtype. Use of interfaces as instance variables have to be as a subtype of the classes implementing the interface.

A class should not have too many responsibilities (some say three is a maximum). A Client class can delegate responsibilities or services to an interface. The service is provided by a ServiceProvider who is implementing the interface. The Client class and the ServiceProvider class only communicate through the interface. The client and the service provider do not know about each other (indirection). Every service provider who is implementing the interface is accepted by the client, making the use of interfaces a flexible programming tool.

The condensed description of design pattern is: a solution to a problem in a certain context. One of the first formal descriptions of design pattern was the GoF book (1995). The GoF (Gang of Four) described a basic rule of reusable object-oriented design: "Program to an interface, not an implementation." Grand (2002) makes the use more formal by declaring a basic design pattern called an Interface Pattern. Grand defines an interface pattern because the interface construct is present in many design patterns, giving flexibility and reusability to the construction of software.

In the example below three different graphical user interfaces (here the word interface is used about the user interface and not the interface construct) are used to present the result of three different ways of reading a file. The client classes of the code sample are: BlueGUI, RedGUI and YellowGUI. The three other classes providing a service reading different file types. The provided services are the classes: XMLInput (reading an XML file), INIInput (reading an INI/text file) and BinInput (reading a binary file). The three client classes and the three services providing classes communicate indirectly through an interface called IInput. This gives the flexibility of nine possible combinations when building an application. The purpose of this article is not to show how to read XML, INI text files or binary files, but to show how to use an interface as a means of indirection between communicating sets of classes.

Class diagram shows the relationship between the three client classes (colour GUIs) and three service providing classes (input readers). The three client classes are using an instance of the interface and the three service providers are implementing the interface. Sub-typing the three implementing classes of the interface is used to indirectly attach the client and service provider, in a driver class. In the sample code checkboxes are used to select the two classes to couple from the two set of classes.

In the Interface Demo application the driver code is controlled by radio buttons. The radio buttons are placed on top of the UML illustration to clarify the class relations.

It is easy to extend the application with new functionalities. If the customer wants a new functionality, say a new service provider reading from another source which is not currently present, the problem is solved by writing a new reader class implementing IInput. This is a good way of extending the system since the developer does not have to change any existing code. Changing existing code could introduce new errors. A rule can be expressed as: "Once written don't change." Also, if the original developer is busy with other jobs, the job of implementing the new functionality can be given to his colleague. The colleague who does not know the design and perhaps does not have the time to understand it, just writes a class capable of reading the new file format, so all that the new developer has to do extra is to implement the IInput interface. The original developer can then easily implement the new class in the system.

As a final note on interfaces a word on the as and is operators could be useful. Objects can be referenced by casting an object to one of its implemented interfaces. The new object can then call those interface members. This is the reverse process of the above driver code.

iInput = xmlInput as IInput;
if (null != iInput)
…

The as operator checks if both the types are compatible and casts xmlInput to iInput. The is operator only checks if the two types are compatible.

The major advantage of using interfaces is that you add an extra dimension of communication to your design. Instead of only accessing classes through class inheritance, with interfaces you can make a backdoor open for classes implementing a specific interface. This construct makes the software flexible for future changes. The client using your class through a method argument or instance variable will not have to know anything about the class, but that it implements a specific interface. Meaning: all classes implementing a given interface can be used. Uses of the interface construct decouple your design resulting in low coupling and high cohesion. Low coupling means that when classes are decoupled they do not depend closely on each other. The chance of failures, faults or errors getting thrown when you make changes to existing code will be lower when the classes are decoupled. Often you do not have to change existing code. All you do is add new code. Design of interfaces and their use in design patterns is at a more abstract level compared to the abstract level where your code is at. In fact, design patterns and the use of interface abstracts the code itself. Meaning that if you have your design ready you can make the source code either in Java or C# directly from the design. This also means that when you are looking for literature on design pattern, and use of interface constructs, Java books are fine too. The best books (besides the GoF) on design pattern are still the Java ones.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

You did well in the discussion of "Diagram of the Interface Logic" and onward. But the code does NOT reflect the context of the problem. In real life, all GUI and Input classes would be in separate DLLs. They exist and can operate quite separately without knowledge of each other - and so they must be able to compile as separate units. But your code in the article uses IInput all over the place. Furthermore, the demo source code is all in one project, and all in one namespace - so everybody knows everything about everyone else. No wonder things compile.

Also, your GUIs call NotifyOutput which is a public method of *each* Input class. All you have to do is reference each class and decide which to call in the driver code based on the radio buttons. You don't need an interface at all.

If you want this article to be helpful you will need to separate the pieces and construct the code so that an interface is essential. This has not worked for me so far, and I'm looking for the method to do it. Try the following:

Use only one GUI and one Input class. Consider these fixed; no changes are permitted. What needs to be dsigned and coded is the starup program and the driver and potentially a separate class that implements the interface IInput.

Now for the GUI class. Its designer intended it to call GetOutput (change from NotifyOutput). Adding a call to NotifyOutput is not permitted. The GetOutput call is inside the GUI code. How is that unit compiled? With or without the IInput interface(with GetOutput instead of NotifyInput)? I have not succeeded either way, so far.Now for the GUI class. Its designer intended it to call GetOutput (change from NotifyOutput). Adding a call to NotifyOutput is not permitted. The GetOutput call is inside the GUI code. How is that unit compiled? With or without the IInput interface? I have not succeeded either way, so far.

The implemented interface will have to have a method named GetOutput and that method will call the NotifyOutput method in the Input class. Where is the interface implemented? In the driver? In a separate wrapper class? Again, I have no success in having this compile.

When somebody wish to learn something, he/she has to solve several challenges in his/her mind.

In my experience, I have found that if I want to handle what I learnt to the level of mastering. I have to understand in a deep way the purpose that the creators of the subject thought about it. Then the rest is easy: to fill some details and to put in practice.

You have the talent to teach in an easy way, what others manage as the complex concepts. Believe me Jacob, you can write great books with the benefit of your talent.