Liskov Substitution Principle (LSP) in C# – Explained with Clear Examples

What is the Liskov Substitution Principle (LSP) in C#?

The Liskov Substitution Principle (LSP) in C# states:

Objects of a derived class should be replaceable with objects of the base class without breaking the application.

In simple words:
* Child class should behave like its parent class
* Replacing parent with child must not change correctness

Why LSP is Important in Real Projects

In enterprise .NET applications:

  • Violating LSP causes unexpected runtime bugs
  • Polymorphism stops working correctly
  • Code becomes fragile and unpredictable

Following LSP ensures:

  • Safe inheritance
  • Reliable polymorphism
  • Clean and predictable behavior

Simple Real-Life Example

Imagine:

  • A Bird class can Fly()
  • A Sparrow can fly ✅
  • A Penguin cannot fly ❌

If Penguin inherits from Bird and overrides Fly() incorrectly,
➡️ LSP is violated


LSP Violation Example (Very Common in Interviews)

public class Bird
{
    public virtual void Fly()
    {
        Console.WriteLine("Bird is flying");
    }
}

public class Penguin : Bird
{
    public override void Fly()
    {
        throw new Exception("Penguins cannot fly");
    }
}

❌ What’s wrong here?

  • Penguin cannot substitute Bird
  • Code breaks at runtime
  • Violates LSP

Correct Design Following LSP

public abstract class Bird
{
}

public interface IFlyingBird
{
    void Fly();
}
public class Sparrow : Bird, IFlyingBird
{
    public void Fly()
    {
        Console.WriteLine("Sparrow is flying");
    }
}
public class Penguin : Bird
{
    // No Fly method
}

* Benefits:

  • No forced behavior
  • Correct abstraction
  • Safe substitution

Another Classic LSP Violation (Rectangle–Square Problem)

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

    public int Area() => Width * Height;
}

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

    public override int Height
    {
        set { base.Width = base.Height = value; }
    }
}

❌ Issue:

  • Square breaks Rectangle behavior
  • Area calculation becomes unpredictable
  • Very popular interview trap

How to Detect LSP Violation

Ask yourself:

  • Does child class throw exceptions not expected by parent?
  • Does it weaken parent class behavior?
  • Does it change expected output?

If yes, LSP is violated.


LSP + Polymorphism (Key Concept)

Polymorphism works correctly only when LSP is followed.
Otherwise:

  • Runtime bugs appear
  • Unit tests fail unexpectedly

Interview Question (Must Know)

Q: Difference between Inheritance and LSP?

Answer:

  • Inheritance is a language feature
  • LSP is a design rule
  • You can inherit a class and still violate LSP

Key Takeaways

  • Not every “is-a” relationship is valid
  • LSP protects runtime behavior
  • Prefer composition over inheritance when in doubt
  • Extremely important for senior .NET roles

In the next post, we will explore the Interface Segregation Principle (ISP) with real-world C# examples and refactoring techniques.

You may also read Solid Principles to understand concept.

Leave a Comment

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

Scroll to Top