Proving post conditions for code that does not implement Code Contracts
I'm learning how to design by contract by annotating my existing code with Contract.Requires()
and Contract.Ensures()
wherever I can.
After fixing the warnings that were actually caused by me, I started to notice that many methods in the framework do not ensure their post conditions. This concerns me, because the static checker is now giving me false positives about possible violations of my preconditions.
An example of a method that doesn't implement Code Contracts:
CultureInfo.GetCultureInfo(string)
As stated by the documentation:
In no case will it ever return null
. Still, I can't use this:
Contracts.Requires(culture != null)
If I do, the static checker gives me this:
CodeContracts: requires unproven: culture != null
So, what do I do? Ignore the warning and write a comment with a link to the documentation? Or is there a way to prove post conditions for a method that someone else wrote?
edit
Making assumptions seems to make the analyzer shut up, but only until the next time that I write the same line of code.
var culture = CultureInfo.GetCultureInfo("en");
Contract.Assume(culture != null);
MyPreconditionalMethod(culture);
I've looked at the [ContractClassFor()]
attribute, but it requires a mutual handshake. :
Instead of Contracts.Requires(culture != null)
, you could try Contracts.Assume(culture != null)
. This gives the static analyzer a hint that, at that point in your code's execution, culture
will not be null. The static analyzer will use this assumption when making further analysis on your code.
Update
So, if you have a method, say:
public int DoSomething(SomeObject o, int i)
{
Contract.Requires(o != null);
Contract.Requires(i > 0);
// You could combine the conditionals in the Requires: o != null && i > 0
Contract.Ensures(/* some post condition */);
int returnValue = 0;
// Do some stuff
return returnValue;
}
public void SomeMethodThatDoesSomething(int i)
{
Contract.Requires(i > 0)
// Do some stuff
}
public void SomeMethodThatCoordinatesActivities()
{
int result = DoSomething(new SomeObject(), 10);
Contract.Assume(result > 0);
SomeMethodThatDoesSomething(result);
}
The static analyzer won't be able to prove that result
in SomeMethodThatCoordinatesActivities
is greater than 0
, so you'll get a contract requires unproven: i
warning. By using Contract.Assume
in the calling method, you give a hint to the static analyzer to assume that at that point, result
will be greater than 0
when calling SomeMethodThatDoesSomething
and the unproven
warning will not be given.
One interesting thing to note in the code above is that if I do actually provide the following post condition on the method DoSomething
:
Contract.Ensures(Contract.Result<int>() > 0);
then I wouldn't need the Contract.Assumes(...)
call in SomeMethodThatCoordinatesActivities
because I've told the static analyzer that when DoSomething
returns, it's result will be greater than 0
, so no assumption needs to be made. The static analyzer knows this will be true, and an unproven
warning will never be given.
上一篇: 代码合同虚假肯定和压制
下一篇: 为不执行代码合同的代码验证后置条件