Liskov substitution principle (LSP) says:
Preconditions cannot be strengthened in a subtype.
In C#, I could violate the whole principle as follows:
public class A
{
public virtual void DoStuff(string text)
{
Contract.Requires(!string.IsNullOrEmpty(text));
}
}
public class B : A
{
public override void DoStuff(string text)
{
Contract.Requires(!string.IsNullOrEmpty(text) && text.Length > 10);
}
}
But, what would happen if A.DoStuff
would be an abstract
method:
public class A
{
public abstract void DoStuff(string text);
}
public class B : A
{
public override void DoStuff(string text)
{
Contract.Requires(!string.IsNullOrEmpty(text));
}
}
Now A.DoStuff
is contractless. Or its contract is just everything allowed.
So, is B.DoStuff
precondition violating Liskov substitution principle?
I'd argue that it's not. An abstract method by definition has no preconditions because there is no implementation. It would be the same as arguing if implementing an interface breaks LSP.
Saying
A.DoSomething()
is contracless is an untrue premise.A.DoSomehing()
is undefined, therefore it can not have a contract further than its signature.Yes, you can break the principle very easily, not only in C#.
It only states:
In your example the type B does not fulfill the property of offering a method
DoStuff
that works with short texts, despite its supertype A fulfilling it. So the principle is violated.It's up to the programmer to uphold the principle. A property could also be "it does the right thing", which you could easily break by having a subtype with a wrong implementation of a method.
It depends on what defines the contract.
The LSP is a theoretical construct, it does not depend on a specific language or implementation, such as C#'s "Code Contracts" feature.
The contract can be defined by:
Contract.Requires
On the last two will be verified by the compiler. However, the first three can be part of the contract as well! Consider the following example:
The name and the documentation of the
Remove
method define a clear precondition. Verifying in an implementation that the string to be removed has previously been added does not violate the LSP. Verifying that the string has at least 5 characters would violate the LSP.