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.
