The following are some examples I've collected that demonstrate how Liskov Substitution Principle could be violated.
NOTE: Before continue if you need more details about the definition of Liskov Substitution Principle refer to its Wikipedia page Liskov substitution principle.
NOTE: The below examples don't cover all the possibilities of violating LSP.
NotImplementedExceptionfrom a derived/implementation class is a sign that the parent-child relation is not following LSP. Here in the code snippet
IBirdclass cannot represent
Duckas it has no definition for flying.
virtualparent method in a child class using the
newkeyword also violates LSP. In the code below when the declaration type is changed from the base class
EmployeeAnnualBonusto the derived class
ManagerAnnualBonusthe value of the annual bonus is changed, which means that they cannot be substitutable without altering the expected result.
overridekeyword should be used instead.)
Returning a value of a type that has restrictions that are unknown from the method's signature. Such as returning a value of type
ReadOnlyCollectionfrom a derived class' method while the return type in its signature is
ICollection. The code below demonstrates how this approach is making unexpected behavior for the code consumer.
Adding an implementation for a derived method in a way that violates the system code's policy or conventions (if there is any); like when a derived method returns a
nullvalue for a list when there is a convention not to return
nullfor empty collections but instead to return initialized collections with zero items count.
It's recommended to keep code components (classes or projects) separated and to depend on abstractions instead of concrete implementations, and that makes applying Liskov Substitution principle more important. The implementation of the derived classes may not be known for the code consumer or at design time and implementing a method that returns a value or accepts parameters in a way that is unclear from its interface (or base class) will mislead who calls that code which in turns may break the code execution or result in unexpected behaviors at run time.