Liskov Substitution Principle in C#

Liskov Substitution Principle in C# with Examples

In this article, I am going to discuss the Liskov Substitution Principle in C# with Examples. Please read our previous article before proceeding to this article where we discussed the Open-Closed Principle in C# with an example. The Letter L in SOLID stands for Liskov Substitution Principle which is also known as LSP. As part of this article, we are going to discuss the following pointers in detail.

Liskov Substitution Principle in C# with a real-time example

What is the Liskov Substitution Principle in C#?

The Liskov Substitution Principle is a Substitutability principle in object-oriented programming Language. This principle states that, if S is a subtype of T, then objects of type T should be replaced with the objects of type S.

In simple words we can say that, when we have a base class and child class relationships i.e. inheritance relationships, then, if we can successfully replace the object/instance of a parent class with an object/instance of the child class, without affecting the behavior of the base class instance, then it is said to be in Liskov Substitution Principle. If you are not getting this point properly, don’t worry, we will see some real-time examples to understand this concept.

For example, a father is a teacher whereas his son is a doctor. So here, in this case, the son can’t simply replace his father even though both belong to the same family.

Example: Without using the Liskov Substitution Principle in C#:

Let us first understand one example without using the Liskov Substitution Principle in C#. In the following example, first, we create the Apple class with the method GetColor. Then we create the Orange class which inherits the Apple class as well as overrides the GetColor method of the Apple class. The point is that an Orange cannot be replaced by an Apple, which results in printing the color of the apple as Orange as shown in the below example.

namespace SOLID_PRINCIPLES.LSP
{
    class Program
    {
        static void Main(string[] args)
        {
            Apple apple = new Orange();
            Console.WriteLine(apple.GetColor());
        }
    }
    public class Apple
    {
        public virtual string GetColor()
        {
            return "Red";
        }
    }
    public class Orange : Apple
    {
        public override string GetColor()
        {
            return "Orange";
        }
    }
}

As you can see in the above example, Apple is the base class and Orange is the child class i.e. there is a Parent-Child relationship. So, we can store the child class object in the Parent Reference variable i.e. Apple apple = new Orange(); and when we call the GetColor i.e. apple.GetColor(), then we are getting the color of the Orange not the color of Apple. That means once the child object is replaced i.e. Apple storing the Orange object, the behavior is also changed. This is against the LSP Principle. The Liskov Substitution Principle in C# states that even the child object is replaced with the parent, the behavior should not be changed. So, in this case, if we are getting the color of Apple instead of Orange, then it follows the Liskov Substitution Principle. That means there is some issue with our software design. Let us see how to overcome the design issue and makes the application follow Liskov Substitution Principle.

Example Using the Liskov Substitution Principle in C#

Let’s modify the previous example to follow the Liskov Substitution Principle. Here, first, we need a generic base class such as Fruit which is going to be the base class for both Apple and Orange. Now you can replace the Fruit class object with its subtypes either Apple and Orage and it will behave correctly. Now, you can see in the below code, we created the super Fruit class as an abstract class with the GetColor abstract method and then the Apple and Orange class inherited from the Fruit class and implement the GetColor method. 

namespace SOLID_PRINCIPLES.LSP
{
    class Program
    {
        static void Main(string[] args)
        {
            Fruit fruit = new Orange();
            Console.WriteLine(fruit.GetColor());
            fruit = new Apple();
            Console.WriteLine(fruit.GetColor());
        }
    }
    public abstract class Fruit
    {
        public abstract string GetColor();
    }
    public class Apple : Fruit
    {
        public override string GetColor()
        {
            return "Red";
        }
    }
    public class Orange : Fruit
    {
        public override string GetColor()
        {
            return "Orange";
        }
    }
}

Now, run the application and it should give the output as expected. Here we are following the LSP as we are now able to change the object with its subtype.

In the next article, I am going to discuss the Interface Segregation Principle in C# with Examples. Here, in this article, I try to explain the Liskov Substitution Principle in C#. I hope you enjoy this article.

8 thoughts on “Liskov Substitution Principle in C#”

  1. blank
    Venkataramana Reddy

    I can do the same implementation without creating an interface.
    Apple apple = new Orange();
    Console.WriteLine(apple.GetColor());
    apple = new Apple();
    Console.WriteLine(apple.GetColor());

    It will gives the output as expected.
    Could please explain with any other example.

  2. blank

    Apple apple = new Orange();

    this will give output as orange. As per principle it should not print “The point is that an Orange cannot be replaced by an Apple, which results in printing the color of apple as Orange”.

    So if you call by Abstract object it will not allow you to create object like this
    Apple apple = new Orange();

  3. blank

    for the example without using the Liskov Substitution Principle, you should remove the “virtual” keyword and replace the “override” by “new” instead. So, it will more understandable.

  4. blank

    I think your example that without using the Liskov Substitution Principle is wrong, it follows the principal.
    Apple apple = new Orange();
    Console.WriteLine(apple.GetColor());
    Orange apple1 = new Orange();
    Console.WriteLine(apple1.GetColor());

    I agree with PHINEAS VUONG, with new key word will not follow the principal

  5. blank

    i think a way it might be more clear is to say Fruit can be any type and any color, but a orange cannot be the color red and an apple cannot be of color orange , meaning we cannot replace a orange with an apple but fruit can be replaced with an orange or an apple because they are both Fruits, a apple is not an orange and a orange is not a apple.

    Lets say the base class was Cooldrinks, and a sub class was Coke and the other Fanta Orange, then we would be able to replace the Base Type (cooldrinks) with either Coke or Fanta Orange because they are both Cooldrinks but if we ask for a Coke we do not expect or want a Fanta we want a Coke , if we ask for cooldrink we do not know what we will receive and any of the 2 would be sufficient. So if the base type is the same any of the 2 would work but we specifically want one sub type another would not be sufficient.

    Hope this helps out.

Leave a Reply

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