Interface Segregation Principle in C#

Interface Segregation Principle in C# with Examples

In this article, I will discuss the Interface Segregation Principle in C# with Examples. Please read our previous article before proceeding to this article, where we discussed the Liskov Substitution Principle in C# with Examples. The letter I in the SOLID Design Principle stands for Interface Segregation Principle, also known as ISP. As part of this article, we will discuss the following pointers in detail.

  1. What is the Interface Segregation Principle in C#?
  2. Example without using the Interface Segregation Principle in C#.
  3. Example using the Interface Segregation Principle in C#.
  4. How to Use Interface Segregation Principle in C#?
What is the Interface Segregation Principle in C#?

The Interface Segregation Principle states Clients should not be forced to implement any methods they don’t use. Rather than one fat interface, numerous little interfaces are preferred based on groups of methods, with each interface serving one submodule.

Let us break down the above definition into two parts.

  1. First, no class should be forced to implement any method(s) of an interface they don’t use.
  2. Secondly, instead of creating large or, you can say, fat interfaces, create multiple smaller interfaces with the aim that the clients should only think about the methods that are of interest to them.

As per the Single Responsibility Principle of SOLID, interfaces should also have a single responsibility, like classes. That means we shouldn’t force any class to implement any method(s) they don’t require.

Example to Understand Interface Segregation Principle in C#.

Let us understand the Interface Segregation Principle in C# with an example. Please have a look at the following diagram. Here, we have one interface and two classes implementing that Interface.

Example to Understand Interface Segregation Principle in C#

As you can see in the above diagram, we have an interface, i.e., IPrinterTasks declared with four methods. Now, if any class wants to implement this interface, then that class should and must have to provide the implementation to all four methods of the IPrinterTasks interface. As you can see in the above diagram, we have two classes, HPLaserJetPrinter and LiquidInkjetPrinter, who want the printer service.

But the requirement is the HPLaserJetPrinter wants all the services provided by the IPrinterTasks while the LiquidInkjetPrinter wants only the Print and Scan service of the printer. As we have declared all the methods within the IPrinterTasks interface, the LiquidInkjetPrinter class must provide implementation to Scan and Print methods along with the Fax and PrintDulex methods, which are not required by the class. This violates the Interface Segregation Principle in C#, forcing the class to provide the implementation they don’t require.

Example Without using the Interface Segregation Principle in C#:

Let us first see the example without following the Interface Segregation Principle, and then we will see the problem. and finally, we will rewrite the same example by following Interface Segregation Principle using C# Language.

IPrinterTasks.cs

Create a class file named IPrinterTasks.cs, then copy and paste the following code. Here, IPrinterTasks is an interface and contains the declaration of four methods. By default, interface methods are public and abstract, so the child class of this interface needs to provide the implementation of all these methods.

namespace SOLID_PRINCIPLES.ISP
{
    public interface IPrinterTasks
    {
        void Print(string PrintContent);
        void Scan(string ScanContent);
        void Fax(string FaxContent);
        void PrintDuplex(string PrintDuplexContent);
    }
}
HPLaserJetPrinter.cs

Next, create a class file with the name HPLaserJetPrinter.cs and copy and paste the following code. Here, the HPLaserJetPrinter implements the IPrinterTasks interface and provides implementations for all four methods. This class requires all printer services, so there is no issue in implementing all interface methods.

using System;
namespace SOLID_PRINCIPLES.ISP
{
    public class HPLaserJetPrinter : IPrinterTasks
    {
        public void Print(string PrintContent)
        {
            Console.WriteLine("Print Done");
        }

        public void Scan(string ScanContent)
        {
            Console.WriteLine("Scan content");
        }

        public void Fax(string FaxContent)
        {
            Console.WriteLine("Fax content");
        }

        public void PrintDuplex(string PrintDuplexContent)
        {
            Console.WriteLine("Print Duplex content");
        }
    }
}
LiquidInkjetPrinter.cs

Next, create a class file named LiquidInkjetPrinter.cs and copy and paste the following code. Here, the LiquidInkjetPrinter implements the IPrinterTasks interface and provides implementations for all four methods. But, this class only requires the Print and Scan services. This class does not require Fax and PrintDuplex services but still implements these two methods. This violates the Interface Segregation Principle as we force the class to implement two methods they don’t require.

using System;
namespace SOLID_PRINCIPLES.ISP
{
    class LiquidInkjetPrinter : IPrinterTasks
    {
        public void Print(string PrintContent)
        {
            Console.WriteLine("Print Done");
        }

        public void Scan(string ScanContent)
        {
            Console.WriteLine("Scan content");
        }

        public void Fax(string FaxContent)
        {
            throw new NotImplementedException();
        }

        public void PrintDuplex(string PrintDuplexContent)
        {
            throw new NotImplementedException();
        }
    }
}
Why are we Facing this problem?

We face the above problem because we declare all the methods in a single class. As per Inheritance Rules, the child class will implement all interface methods. Because of this, the LiquidInkjetPrinter class provides implementation to all IPrinterTasks Interface methods. We can overcome this problem by following the Interface Segregation Principle. Let us proceed and try to understand how we can rewrite the same example by following the Interface Segregation Principle using C# Language.

Example using Interface Segregation Principle in C#:

Please have a look at the following image. As you can see in the image below, we have split that big interface into three small interfaces. Each interface now has some specific purpose. 

Example using Interface Segregation Principle in C#

Now, if any class wants all the printer services, then that class needs to implement all three interfaces. In our example, HPLaserJetPrinter wants all the printer services. So, the HPLaserJetPrinter class needs to implement all three interfaces and provide implementations of all interface methods, as shown in the below image.

Example using Interface Segregation Principle in C#

Now, if any class wants the Scan and Print services, then that class needs to implement only the IPrinterTasks interfaces. In our example, LiquidInkjetPrinter wants only the Scan and Print services. So, the LiquidInkjetPrinter class must implement only the IPrinterTasks interfaces and provide implementations for Print and Scan methods, as shown in the image below.

What is Interface Segregation Principle in C#?

The Complete Example Code is Given Below:

First, modify the IPrinterTasks.s class file as follows. Here, we are splitting the big interface into three interfaces. Now, Each interface has some specific purpose. And based on the requirement, the child class will implement 1, 2, or all the interfaces.

namespace SOLID_PRINCIPLES.ISP
{
    public interface IPrinterTasks
    {
        void Print(string PrintContent);
        void Scan(string ScanContent);
    }
    interface IFaxTasks
    {
        void Fax(string content);
    }
    interface IPrintDuplexTasks
    {
        void PrintDuplex(string content);
    }
}

Next, modify the HPLaserJetPrinter.cs class file as follows. The HPLaserJetPrinter printer class requires all the printer services, hence implementing all three interfaces and providing implementation to all four methods.

using System;
namespace SOLID_PRINCIPLES.ISP
{
    public class HPLaserJetPrinter : IPrinterTasks, IFaxTasks, IPrintDuplexTasks
    {
        public void Print(string PrintContent)
        {
            Console.WriteLine("Print Done");
        }
        public void Scan(string ScanContent)
        {
            Console.WriteLine("Scan content");
        }
        public void Fax(string FaxContent)
        {
            Console.WriteLine("Fax content");
        }
        public void PrintDuplex(string PrintDuplexContent)
        {
            Console.WriteLine("Print Duplex content");
        }
    }
}

Next, modify the LiquidInkjetPrinter.cs class file as follows. The LiquidInkjetPrinter printer class requires only the Print and Scan Printer services and hence implements only the IPrinterTasks interface and provides implementation to Print and Scan methods.

using System;
namespace SOLID_PRINCIPLES.ISP
{
    class LiquidInkjetPrinter : IPrinterTasks
    {
        public void Print(string PrintContent)
        {
            Console.WriteLine("Print Done");
        }
        public void Scan(string ScanContent)
        {
            Console.WriteLine("Scan content");
        }
    }
}

Now, you can see the LiquidInkjetPrinter class is not implementing the Fax and PrintDuplex methods as these services are not required by the LiquidInkjetPrinter class. That means now our application design follows the Interface Segregation Principle. Now, you can test the functionality of the two classes by modifying the Program class code as follows.

using System;
namespace SOLID_PRINCIPLES.ISP
{
    public class Program
    {
        static void Main(string[] args)
        {
            //Using HPLaserJetPrinter we can access all Printer Services
            HPLaserJetPrinter hPLaserJetPrinter = new HPLaserJetPrinter();
            hPLaserJetPrinter.Print("Printing");
            hPLaserJetPrinter.Scan("Scanning");
            hPLaserJetPrinter.Fax("Faxing");
            hPLaserJetPrinter.PrintDuplex("PrintDuplex");

            //Using LiquidInkjetPrinter we can only Access Print and Scan Printer Services
            LiquidInkjetPrinter liquidInkjetPrinter = new LiquidInkjetPrinter();
            liquidInkjetPrinter.Print("Printing");
            liquidInkjetPrinter.Scan("Scanning");

            Console.ReadKey();
        }
    }
}

When you run the above code, you will get the following output.

Complete Example Code

Note: A solution to having a better code always comes down to a word small: small method, small class, small interface. So, if you split your code into smaller chunks, it will be easier to change and maintain it.

In the example below, you can see how the Interface Segregation Principle is applied in C#. The following example demonstrates that the Worker class implements the IWorker interface, while the SuperWorker class implements both the IWorker and IEater interfaces. The Manager class only depends on the IWorker interface, which follows the Interface Segregation Principle by not forcing classes to implement interfaces that are not required.

namespace SOLID_PRINCIPLES.ISP
{
    public interface IWorker
    {
        void Work();
    }

    public interface IEater
    {
        void Eat();
    }

    public class Worker : IWorker
    {
        public void Work()
        {
            // Perform work-related tasks
        }
    }

    public class SuperWorker : IWorker, IEater
    {
        public void Work()
        {
            // Perform complex work tasks
        }

        public void Eat()
        {
            // Eat during breaks
        }
    }

    public class Manager
    {
        private IWorker _worker;

        public Manager(IWorker worker)
        {
            _worker = worker;
        }

        public void Manage()
        {
            _worker.Work();
        }
    }
}

By following these guidelines, you can create more focused and cohesive interfaces that improve the maintainability and flexibility of your codebase in accordance with the Interface Segregation Principle.

In the next article, I will discuss Multiple Real-Time Examples of the Interface Segregation Principle (ISP) in C#. I explain the Interface Segregation Principle in C# with Examples in this article. I hope you enjoy this Interface Segregation Principle in C# with Examples article.

9 thoughts on “Interface Segregation Principle in C#”

Leave a Reply

Your email address will not be published. Required fields are marked *