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

回眸只為那壹抹淺笑 提交于 2019-12-06 20:12:42

问题


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?


回答1:


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.




回答2:


I'd like to note that you can do what Jon suggested (this answers adds upon his) but also have your contract without violating LSP.

You can do so by replacing the override keyword with new.

The base remains the base; all you did is introduce another functionality (as the keywords literally suggest).

It's not ideal for static-checking because the safety could be easily casted away (cast to base-class first, then call the method) but that's a must because otherwise it would violate LSP and you do not want to do that obviously. Better than nothing though, I'd say.

In an ideal world you could also override the method and call the new one, but C# wouldn't let you do so because the methods would have the same signatures (even tho it would make perfect sense; that's the trade-off).



来源:https://stackoverflow.com/questions/7312866/why-cant-i-add-contract-requires-in-an-overridden-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!