SOLID Principles

Implementing LSP in C#

To adhere to LSP, subclasses should not:

  • Remove behavior that clients of the base class expect.
  • Violate invariants of the base class.
  • Contradict postconditions of the base class.
Example: Shapes and Areas

Let's illustrate LSP with an example involving shapes.

Violating LSP

Consider a base class Rectangle and a derived class Square.


public class Rectangle
{
    public virtual double Width { get; set; }
    public virtual double Height { get; set; }

    public double Area()
    {
        return Width * Height;
    }
}

public class Square : Rectangle
{
    public override double Width
    {
        get { return base.Width; }
        set
        {
            base.Width = value;
            base.Height = value;
        }
    }

    public override double Height
    {
        get { return base.Height; }
        set
        {
            base.Height = value;
            base.Width = value;
        }
    }
}

In this example, the Square class violates LSP because it changes the behavior of the Width and Height properties, causing the Rectangle's expectations to be violated. When a Square object is used in place of a Rectangle, the behavior is not as expected.

Adhering to LSP

To adhere to LSP, we need to ensure that the behavior of derived classes does not break the expectations set by the base class. One way to achieve this is by using interfaces or by redefining the class hierarchy to better represent the problem.


public abstract class Shape
{
    public abstract double Area();
}

public class Rectangle : Shape
{
    public double Width { get; set; }
    public double Height { get; set; }

    public override double Area()
    {
        return Width * Height;
    }
}

public class Square : Shape
{
    public double Side { get; set; }

    public override double Area()
    {
        return Side * Side;
    }
}

In this refactored design, Rectangle and Square both inherit from Shape and implement the Area method. This way, each class adheres to the expectations set by the base class, and using a Square in place of a Shape will not violate LSP.