Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CodeContracts "Required" understanding

I tried the following code to enable some kind of not null checking for retrieved entities to ensure they are exist before doing some concrete business:

protected T GetRequired<T>(object id)
    where T : EntityObject
{
    var obj = Get<T>(id);
    Contract.Requires<ArgumentNullException>(obj != null);
    return obj;
}

But in compile time I'm getting:
After contract block, found use of local variable 'obj' defined in contract block

Am I using Contract.Requires in the wrong way?

like image 316
Sergey Metlov Avatar asked Jul 24 '13 16:07

Sergey Metlov


2 Answers

Am I using Contract.Requires in the wrong way?

Yes, you are. Contract.Requires is about stating preconditions for a method (or property). These are conditions that must be true for method invocation to proceed, otherwise you have a contract violation.

Let's take a look at your code:

var obj = Get<T>(id);
Contract.Requires<ArgumentNullException>(obj != null);

Here, you are trying to use it to ensure that something is true after a method has finished executing (in this case, the Get method). That would be a postcondition and for that you would use Contract.Ensures in the body of Get:

protected T Get<T>(object id) {
    Contract.Ensures(Contract.Results<T>() != null);
    // get and return result
}

Lastly, this compiler error

After contract block, found use of local variable obj defined in contract block

This message is a result of the fact that you can not use Contracts after the contract block, and the contract block appears at the top of body of a method only.

like image 125
jason Avatar answered Sep 22 '22 20:09

jason


It seems that you are trying to do a couple of things at once here:

Contract.Requires should be used on the input parameter directly, e.g. if id should never be null, then do like so:

Contract.Requires<ArgumentNullException>(id != null);

In addition, it seems that you want to guarantee that the result isn't null. Do this like so:

Contract.Ensures(obj != null);

Similarly, additional contracts can be checked by your helper method (Get).

like image 43
StuartLC Avatar answered Sep 23 '22 20:09

StuartLC