Trying to implement cleaner than before, I noticed that it’s sometimes hard to do, especially if you allow .NET framework classes to be passed as arguments. Within just a few days, I stumbled upon the following base classes that do not respect the Liskov Substitution Principle (LSP):
A Stream in .NET has the CanRead, CanSeek and CanWrite methods. Depending on these properties, the Read(), Write() and Seek() methods may throw a NotSupportedException. If you have designed an API that takes a Stream as parameter, I can certainly break it by passing in a Stream that has no capabilities at all. There is no sort of contract between your API and the Stream that require it to be readable, writeable or seekable. But that’s exactly what LSP wants: a reliable contract.
Collections are similar to Streams, except they do not expose their capabilities, e.g. there’s no CanRemove property that a ReadOnlyCollection could set to false. As a result, the Remove() method throws a NotSupportedException, thus breaking your API’s implementation like the Stream did.
Bitmaps do not look dangerous at first, except that the owner might dispose it at any time. If however, you allow to change the format of the bitmap as used in the Save() method. Because some images formats are read-only and cannot be written. This is not documented on MSDN but in KB 316563. So, if you API accepts an ImageFormat, missing compliance of the .NET framework to the LSP may break your application again.