Click here to Skip to main content
15,886,258 members
Articles / Programming Languages / C#

Why Do We Use Interfaces in C#?

Rate me:
Please Sign up or sign in to vote.
4.51/5 (24 votes)
23 Aug 2015CPOL4 min read 27.3K   35   12
Why do we use interfaces in C#

Introduction

In this article, I would not cover anything about interfaces as I have already covered about existence of interfaces in C# and what are interfaces. As soon as we learn about interfaces, we think that it was so easy to know about the interfaces and now at least I can understand a very important concept of C#. But as soon as someone asks where should I use interfaces, we start doubting our knowledge about interfaces and the only example we can give is that C# doesn’t support multiple inheritance, that is why we use interfaces. As long as we are not sure why we use interfaces, our knowledge about them is incomplete.

I have developed a small application here which would help us to understand about the utilization of interfaces.

Project Task: Client would use here Driver(class) to drive a Car(class).

Concepts covered: Following are the concepts which we would cover in this application which in turn would help us to understand about interfaces.

  1. Extensibility
  2. Implementation Hiding
  3. Accessing object through interfaces
  4. Loose Coupling

Before stating the discussion about the code, I would like to take you through the various components of the project as shown in the following figure:

The project to understand interfaces in C#

The project to understand interfaces in C#

InterfaceUtilization is the client which would be using the interface components to achieve the functionality for the task. The client only contains the references for the Interfaces and Factory namespaces.

Car and Driver are the assemblies which contain the classes which implement the ICar and IDriver interfaces from the Interfaces namespace. These classes are the entities whose instances would be used to achieve the desired functionality.

Interfaces is the namespace which contains the contracts or interfaces which would in turn be implemented by the individual classes (in our class, Car and Driver).

Factory is the assembly which is used by the client (InterfaceUtilization) to create and return the instances of the entities (Car and Driver). Factory has the references of the Car, Driver as well as the Interfaces namespaces.

Now, I would like to discuss all the points here one by one which I have noted down earlier.

  1. Extensibility - We can achieve extensible using the interfaces in C#. In this example, I have two interfaces, ICar and IDriver which are implemented by NormalCar, RaceCar and Driver, RaceDriver respectively. We can easily extend the interfaces to create new classes which implement the same contract functionalities. Suppose if I want to add a new car type apart from which are shown in the above figure as shown below:
    C#
    public class VintageCar:ICar
        {
            private string modelName;
            public VintageCar(string modelName)
            {
                MoodelName = modelName;
            }
    
            #region ICar Members
    
            public string MoodelName
            {
                get{  return modelName; }
                set{  modelName = value; }
            }
    
            public void DriveCar(IDriver driver)
            {
                if (driver.YearsOfExperience > 10)
                    driver.Drive();
            }
    
            #endregion
        }

    And to get an instance of this car type, I have to add a new factory method in the factory class as shown below:

    C#
    public static ICar CreateVintageCar(string modelName)
            {
                return new VintageCar(modelName);
            }

    Now, to use this newly created car type in client, we just have to call the above method of factory as shown below:

    C#
    IDriver myDriver= Factory.Factory.CreateDriver("vikram", 38, 5);
                ICar vintageCar = Factory.Factory.CreateNormalCar("Old Toyota");
                vintageCar.DriveCar(myDriver);

    From the above example, we can see that we easily extend a particular interface without having much trouble as our interface already contains the necessary data member and member functions which are needed for a particular type.

  2. Implementation Hiding – Our client code doesn’t know anything about the implementation details of both the Driver class as well as the Car class. By this, we can see that the implementation is known to the client. Here, factory class takes care of creating instances of the classes for the client.
    That is why the client knows only about the Interface and Factory namespaces.
  3. Accessing object through interfaces - If we are using classes derived from the interface, in that case there is no need for us to create the classes instances. We can create variables of the particular instance type which in turn will contain the reference of the type which implements that particular interface. And this variable of interface type can be used as parameter and that particular function can use that reference to achieve its functionality. As we can see in the below mentioned example, I have a function of VintageCar which expects parameter of type IDriver interface and in turn used this variable to work on the class reference.
    C#
    public void DriveCar(IDriver driver)
            {
                //years of experience need to be more to handle this car type
                if (driver.YearsOfExperience > 20)
                    driver.Drive();
            }

    This feature helps us to treat different classes as the same type of interface. It means that I can create variable of any type implementing IDriver and pass as argument to DriveCar method.

    C#
    IDriver myDriver= Factory.Factory.CreateDriver("vikram", 38, 5);
                ICar vintageCar = Factory.Factory.CreateNormalCar("Old Toyota");
                vintageCar.DriveCar(myDriver); // prints "Cannot drive this car"
    
                IDriver raceDriver = Factory.Factory.CreateRaceDriver("myname", 40, 20);
         vintageCar.DriveCar(raceDriver); // prints "myname  is driving a race car";
  4. Loose Coupling – As mentioned in the previous point, only an interface type variable can be used to pass as argument which is again helpful to achieve loose coupling. Before explaining this concept, please have a look at the code snippet below:
    C#
    public interface ICar
        	{
               string MoodelName { get; set; }
               void DriveCar(IDriver driver);
        	}

    What we can derive from the above code snippet is that any class which would be implementing ICar interface would be having a definition of DriveCar method which takes IDriver as parameter, now having an interface type as parameter gives us flexibility to provide the argument of class instance which derives from IDriver interface for this function. On the other side, if the parameter would have been any class type variable, it would have been difficult to achieve this flexibility.

Though the above code can be implemented using much more better designing principles, like better use of Factory Pattern, that was not my main concern to write this article.

Please find the solution code for the blog attached here.

The post Why do we use Interfaces in C#? appeared first on Dot Net For All.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
India India
I have 8 years of experience of mostly developing the .NET windows as well as web applications. Passionate about learning and sharing.

Visit my personal blog to know more about the .NET technology and increase your knowledge about C# and .NET. You can always follow me on twitter @dotnetforall.

Comments and Discussions

 
AnswerNice article - my vote of 5 Pin
Liju Sankar12-Sep-15 14:57
professionalLiju Sankar12-Sep-15 14:57 
QuestionNice Article Pin
Santhakumar Munuswamy @ Chennai11-Sep-15 21:54
professionalSanthakumar Munuswamy @ Chennai11-Sep-15 21:54 
QuestionVery good Pin
Michael Breeden28-Aug-15 1:50
Michael Breeden28-Aug-15 1:50 
I have worked for companies that use interfaces and companies that don't. Rarely do I care, though I think they are good practice. It's funny that the project I am working on now has been presenting a potential problem. I haven't hit it yet, but as I add Business Units to the project, I do see a real problem that could crop up. I figured I could solve it with inheritence, but it would be difficult. This article reminds me that the correct solution would be to use interdfaces.

AnswerRe: Very good Pin
DotNetForAll30-Aug-15 18:04
DotNetForAll30-Aug-15 18:04 
QuestionMissing something. Pin
AnotherKen25-Aug-15 16:04
professionalAnotherKen25-Aug-15 16:04 
AnswerRe: Missing something. Pin
DotNetForAll25-Aug-15 16:37
DotNetForAll25-Aug-15 16:37 
GeneralVery good article Pin
LeonardoDaga25-Aug-15 12:17
LeonardoDaga25-Aug-15 12:17 
GeneralRe: Very good article Pin
DotNetForAll25-Aug-15 14:40
DotNetForAll25-Aug-15 14:40 
SuggestionJust what i needed Pin
Jethro Daniel24-Aug-15 19:22
Jethro Daniel24-Aug-15 19:22 
GeneralRe: Just what i needed Pin
DotNetForAll24-Aug-15 20:31
DotNetForAll24-Aug-15 20:31 
GeneralMy vote of 5 Pin
Humayun Kabir Mamun24-Aug-15 18:04
Humayun Kabir Mamun24-Aug-15 18:04 
GeneralRe: My vote of 5 Pin
DotNetForAll24-Aug-15 18:40
DotNetForAll24-Aug-15 18:40 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.