Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I add Contract.Requires in an overridden method?

I'm using code contract (actually, learning using this).

I'm facing something weird to me... I override a method, defined in a 3rd party assembly. I want to add a Contract.Require statement like this:

public class MyClass: MyParentClass
{
    protected override void DoIt(MyParameter param)
    {
        Contract.Requires<ArgumentNullException>(param != null);

        this.ExecuteMyTask(param.Something);
    }

    protected void ExecuteMyTask(MyParameter param)
    {
        Contract.Requires<ArgumentNullException>(param != null);
        /* body of the method */
    }
}

However, I'm getting warnings like this:

Warning 1 CodeContracts: Method 'MyClass.DoIt(MyParameter)' overrides 'MyParentClass.DoIt(MyParameter))', thus cannot add Requires.

[edit] changed the code a bit to show alternatives issues [/edit]

If I remove the Contract.Requires in the DoIt method, I get another warning, telling me I have to provide unproven param != null I don't understand this warning. What is the cause, and can I solve it?

like image 207
Steve B Avatar asked Sep 05 '11 21:09

Steve B


1 Answers

You can't add extra requirements which your callers may not know about. It violates Liskov's Subtitution Principle. The point of polymorphism is that a caller should be able to treat a reference which actually refers to an instance of your derived class as if it refers to an instance of the base class.

Consider:

MyParentClass foo = GetParentClassFromSomewhere();
DoIt(null);

If that's statically determined to be valid, it's wrong for your derived class to hold up its hands and say "No! You're not meant to call DoIt with a null argument!" The aim of static analysis of contracts is that you can determine validity of calls, logic etc at compile-time... so no extra restrictions can be added at execution time, which is what happens here due to polymorphism.

A derived class can add guarantees about what it will do - what it will ensure - but it can't make any more demands from its callers for overridden methods.

like image 95
Jon Skeet Avatar answered Nov 16 '22 00:11

Jon Skeet