Liskov Substitution Principle
Subtypes must be substitutable for their base types without altering the correctness of the program. In other words, if S is a subtype of T, then objects of type T may be replaced with objects of type S without affecting any of the desirable properties of the program, such as correctness and the task performed.
In C#
If a Bird class has a Fly() method, and a Penguin class inherits from Bird but either throws an exception in Fly() or does nothing, it violates LSP if client code expects all Bird objects to fly. A better design might involve interfaces like IFlyable, or rethinking the hierarchy.
First, the violation. Penguin throws where Bird promised to fly, and the client code would crash.
// Potential LSP Violationpublic class Bird{ public virtual void Fly() { Console.WriteLine("Bird is flying"); }}public class Penguin : Bird{ public override void Fly() { throw new NotSupportedException("Penguins can't fly!"); }}// Client code:// public void MakeBirdFly(Bird bird) { bird.Fly(); /* This will crash for Penguin */ }Then one possible way to follow LSP. IFlyable carries the flying, Sparrow is a Bird and is flyable, and Penguin_Better is a Bird but not flyable.
// Adherence to LSP (one possible approach)public interface IFlyable { void Fly(); }public class Sparrow : Bird, IFlyable // Sparrow is a Bird and is Flyable{ public override void Fly() { Console.WriteLine("Sparrow is flying high"); }}public class Penguin_Better : Bird // Penguin is a Bird, but not IFlyable{ // No Fly() method here, or a different non-virtual method like Waddle()}// Client code:// public void MakeItFly(IFlyable flyer) { flyer.Fly(); }Where it matters
LSP is crucial for making sure inheritance hierarchies are semantically sound, and that polymorphismPolymorphismOne call, many behaviors, decided by the actual type at runtime.Opens in a new tab works as expected. Violations can lead to runtime errors or incorrect behavior when derived class objects are used in place of base class objects. LSP reinforces the contract defined by the base type. Method hidingMethod hiding with newSame name in a derived class, but not an override.Opens in a new tab is one way to get into trouble with it.
Sources
- ASP.NET Core Basics: Understanding and Practicing SOLID, Telerik · accessed May 16, 2025
- SOLID Principles In C# With Examples, C# Corner · accessed May 16, 2025