"What is wanted here is something like the following substitution property:
If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T."
BarbaraLiskov, Data Abstraction and Hierarchy, SIGPLAN Notices, 23,5 (May, 1988).
Med andra ord så ska en subklass ha samma betende som sin superklassen detta kan annars leda till märkliga beteende och kan vara svårt att hitta vad som egentligen orsakar felet i ett program.
Detta fick jag och en kollega nyligen erfara när vi jobbar med en produkt som använder sig av .net remoting och en egen implementerad IServerChannelSink för att kryptera data som skickas mellan klient och server.
Vårt problem var att vi fick ett MethodNotSupportedException när vi gjorde anrop från klienten till servern. Till en början trodde vi att det berodde på att .net cachade proxyn vi använde då vi oftast fick fellen i samband vi gjorde förändringar i kontraktet. Felet kunde helt plötsligt uppstå och sedan försvinna helt utan anledning. Om man debugade så kunde det först smälla och om man körde samma metod en gång till direkt efter så fungerade det. Vi testade att först anropa metoden och sedan fånga exceptionet för att sedan göra samma anrop en gång till som för det mesta gick igenom utan något problem.
Till slut kom vi fram till att det uppstod när metoden man anropades namn och hur parametrarna man skickade in såg ut. Så tex. om vi skickade in en 8 tecken lång sträng till en metod så slutade den fungera och vi fick MethodNotSupportedException. Om vi anropade samma metod med sju eller nio tecken låg sträng så fungerade det, vi kunde också byta namn på metoden så började det fungera igen. Vi märkte också om man stängde av krypteringen så fungerade det helt felfritt vilket ledde oss till att tro att det var något med krypteringen som ställde till det.
Efter att ha undersökt hur krypteringen fungerar och kommit fram till att vi fick samma resultat på båda klienten och server sidan så vi kunde konstatera att det inte var något med krypteringen i sig. Efter ytterligare testningar så kom vi fram till att det var CryptoStream som kastade exceptionet när en del metoder och propertys anropades på den. Eftersom vi skickade in den som en Stream till ProcessMessage i System.Runtime.Remoting.BinaryServerFormatterSink så antar den att den kan använda strömen som en vanlig Stream. Vi gjorde ingen vidare efterforskning till varför det bara inträffade vid vissa tillfällen utan löste problemet med att läsa över CryptoStreamen till en MemoryStream.
Att CryptpStrem inte har samma beteende som sin superklass Stream är ett tydligt exempel på att bryta mot LSP och i detta fallet kostade swt oss säkert 20+ timmar och mycket irritation.

Bild av Derick Bailey
