C# Interface Segregation Principle

Summary: in this tutorial, you’ll learn about the C# Interface Segregation Principle (ISP) that promotes the idea of creating small and focused interfaces that are specific to the needs of clients.

Introduction to the C# Interface Segregation Principle

The interface segregation principle is the fourth principle in the five SOLID principles of object-oriented design:

The interface segregation principle suggests that you should not force a client to implement an interface that contains methods that it doesn’t need.

Instead, you should break down larger interfaces into smaller ones that are more focused and targeted to specific use cases.

The interface segregation principle promotes the idea of creating small and cohesive interfaces that are specific to the client’s needs.

Let’s take an example of violating the interface segregation principle:

namespace ISP;

public interface IVehicle
{
    void Run();
    void Fly();
    
}

public class Aircraft : IVehicle
{
    public void Run() => Console.Write("Running");
    public void Fly() => Console.Write("Flying");
}

public class Car: IVehicle
{
    public void Run() => Console.Write("Running");
    public void Fly() => throw new NotImplementedException();
}

public class Program
{
    public static void Main(string[] args)
    {
        // aircraft 
        var aircraft = new Aircraft();
        aircraft.Run();
        aircraft.Fly();

        // car
        var car = new Car();    
        car.Run();
        
        // cannot fly, exception
        car.Fly(); 
    }
}Code language: C# (cs)

How it works.

First, define an interface IVehicle interface that has two methods Run() and Fly():

public interface IVehicle
{
    void Run();
    void Fly();
}Code language: C# (cs)

Second, define an Aircraft class that implements the IVehicle interface:

public class Aircraft : IVehicle
{
    public void Run() => Console.Write("Running");
    public void Fly() => Console.Write("Flying");
}Code language: C# (cs)

Third, define a Car class that also implements the IVehicle interface. Since a regular car cannot fly, it raises an exception in the Fly() method:

public class Car: IVehicle
{
    public void Run() => Console.Write("Running");
    public void Fly() => throw new NotImplementedException();
}Code language: C# (cs)

Finally, create an Aircraft object and call the Run() and Fly() methods. But when we create a Car object and call the Fly() method, it raises an exception:

public class Program
{
    public static void Main(string[] args)
    {
        // aircraft 
        var aircraft = new Aircraft();
        aircraft.Run();
        aircraft.Fly();

        // car
        var car = new Car();    
        car.Run();
        
        // cannot fly, exception
        car.Fly(); 
    }
}Code language: C# (cs)

This is an example of violating the Interface Segregation Principle because the IVehicle forces the Car class to use the Fly() method that it doesn’t need.

Refactoring the program to conform with the Interface Segregation Principle

To fix the issue of violating the interface segregation principle, you need to break down the large interface into smaller ones.

First, segregate the IVehicle interface into two smaller interfaces IFlyable and IRunnable:

public interface IFlyable
{
    void Fly();
}
public interface IRunnable
{
    void Run();
}Code language: C# (cs)

Second, define the Aircraft class that implements both interfaces since the Aircraft class needs both Run() and Fly() methods:

public class Aircraft : IRunnable, IFlyable
{
    public void Run() => Console.Write("Running");
    public void Fly() => Console.Write("Flying");
}Code language: C# (cs)

Third, define the Car class that implements only the IRunnable interface because it only needs the Run() method:

public class Car: IRunnable
{
    public void Run() => Console.Write("Running");
}Code language: C# (cs)

Finally, create Aircraft and Car objects and call their methods respectively in the Main() method of the Program class:

public class Program
{
    public static void Main(string[] args)
    {
        // aircraft 
        var aircraft = new Aircraft();
        aircraft.Run();
        aircraft.Fly();

        // car
        var car = new Car();    
        car.Run();        
  
    }
}Code language: C# (cs)

Put it all together.

namespace ISP;

public interface IFlyable
{
    void Fly();
}
public interface IRunnable
{
    void Run();
}

public class Aircraft : IRunnable, IFlyable
{
    public void Run() => Console.Write("Running");
    public void Fly() => Console.Write("Flying");
}

public class Car: IRunnable
{
    public void Run() => Console.Write("Running");
}

public class Program
{
    public static void Main(string[] args)
    {
        // aircraft 
        var aircraft = new Aircraft();
        aircraft.Run();
        aircraft.Fly();

        // car
        var car = new Car();    
        car.Run();        
    }
}Code language: C# (cs)

Summary

  • C# Interface Segregation Principle (ISP) advocates for small, client-specific interfaces.
Was this tutorial helpful ?