This post is about concretizing the relationship between two abstract design principles and providing a piece of practical advice
The goal of the Liskov Substitution Principle is to make sure that subclasses behave as their superclass parents. The “Is-A” relationship is superceeded by the “Behaves-As-A” relationship. By observing the LSP we enable looser coupling by not making clients of the superclass catalog knowledge of the subclasses.
Implicit in the discussion around LSP is that you are actually consuming the abstract type instead of the concrete types. From the wikipedia entry on the Dependency Inversion Principle:
A. High-level modules should not depend on low-level modules. Both should depend on abstractions.
B. Abstractions should not depend upon details. Details should depend upon abstractions.
Basically, you want the clients of your code to depend on the most abstract possible type. So, as a simple heuristic when you’re writing methods, try using the most abstract type that the clients of your code can use without type casting or reflection. If you’re using ReSharper (which I highly recommend) you’ll get these suggestions automatically–but this is an easy heuristic to apply when you’re writing the method in the first place.
In general, favor interfaces over base classes and base classes over sub-classes (Interfaces are a much weaker coupling than inheritance).