12

I have a very simple class utilizing .NET Code Contracts:

public class ContractSquareRoot
{
    /// <summary>
    /// Makes your life much easier by calling Math.Sqrt for you. Ain't that peachy.
    /// </summary>
    /// <param name="value">The value to calculate the square root from. No negatives!</param>
    /// <returns>The square root of the given value. Obviously always > 0.</returns>
    public double CalculateSquareRoot(double value)
    {
        Contract.Requires<ArgumentException>(0 <= value);
        Contract.Ensures(0 <= Contract.Result<double>());

        double squareRoot = Math.Sqrt(value);

        return squareRoot;
    }
}

When I call the method with a negative value, I expect the static code analysis to warn me about it.

class Program
{
    static void Main(string[] args)
    {

        var barMansSquareroot = new ContractSquareRoot();

        // This should not be possible...
        barMansSquareroot.CalculateSquareRoot(-42);

    }
}

But even if the Contract.Requires fails throwing the desired exception, the static code analysis marks every assertion as correct. Interestingly enough, it warns me about the violation when I change the type of value to int or if I replace <= with <. The misbehaviour is limited to double and float. I am assuming it has something to do with the precision of floating point values.

It even works when I formulate the requirement like this:

Contract.Requires<ArgumentException>(!(0 > value));

Is that a bug or am I doing something wrong?

BartoszKP
  • 34,786
  • 15
  • 102
  • 130
vlow
  • 171
  • 6
  • just out of interest, why wouldn't you allow 0 as a valid value? – thumbmunkeys Oct 09 '14 at 10:43
  • i do want allow 0 as a valid value. the contract should ensure that every value is >= 0. – vlow Oct 09 '14 at 10:48
  • 2
    Definitely interesting, I'd try to contact Francesco, https://visualstudiogallery.msdn.microsoft.com/1ec7db13-3363-46c9-851f-1ce455f66970 – Erti-Chris Eelmaa Oct 09 '14 at 11:40
  • Check if static analysis is turned on at "project properties" -> Code Contracts tab. Didn't you also try "value >= 0" form? :) – mikalai Oct 10 '14 at 18:16
  • @mikilai Yes, static analysis is turned on and works otherwise. I also tried out >= 0 form, same result. – vlow Oct 12 '14 at 10:09
  • @weston I was under the impression that the expression in the brackets is the positive expression of what the contract requires. If so, that would mean that (0 < value) would require every value to be greater than 0 and therefore exclude 0 from the range of valid values. isn't that correct? it should only fail with negative values and therefore behaves correctly when allowing `barMansSquareroot.CalculateSquareRoot(0);` as valid statement. – vlow Oct 12 '14 at 10:10
  • 4
    I see, yes my mistake. I think it was just the order its in. `value >= 0` might be more readable. Same for the result, `Contract.Ensures(Contract.Result() >= 0);` is more readable. – weston Oct 12 '14 at 10:16
  • I think it's not a bug, just a missing feature. The static analysis has limitations, and one of the limitations seems to be that it doesn't understand floating-point arithmetic. There can always be preconditions that are more complex than the static analyser understands, and the design of Code Contracts allows for that (by checking at run time too). –  Oct 12 '14 at 10:20
  • @weston That is true. Static value -> Comparator -> Check value is the form that is used in the Code Contracts documentation. Similar to assertions, where the check value is the second one. But it's obviously more readable the other way around ;) The masked warning is `CodeContracts: Possible precision mismatch for the arguments of ==` which I mentioned in my post. It still should be able to identify -42 as < 0 or at least warn about an ommitted contract. – vlow Oct 12 '14 at 10:24
  • @hvd I understand the complexity of proving, which makes it very difficult to do a static code analysis on floating point arithmetics. Still, I think it is a bug because the contract is marked as `correct`, while it should be masked with a warning of precision mismatch or even that it can't be statically checked. – vlow Oct 12 '14 at 10:29
  • @vlow That's a good point. If you turn the warnings up as high as possible and still get nothing, then I think I agree. –  Oct 12 '14 at 10:34
  • @hvd Yes, the contract is marked as corrct at the highest warning level, even if you check `barMansSquareroot.CalculateSquareRoot(-42);`. The warning is only emmitted if you change the contract to `Contract.Requires((0 <= value));` as suggested by weston. – vlow Oct 12 '14 at 10:44

1 Answers1

1

I hope you might missed to install Microsoft code contract.

You can download Microsoft Code Contracts from Microsoft Research: http://research.microsoft.com/en-us/projects/contracts/

Now on your project properties you will get an extra tab where you can set runtime and static checking.

Joseph
  • 1,054
  • 1
  • 11
  • 25
  • please refer this for additional details https://www.develop.com/csharpcodecontracts – Joseph Oct 27 '14 at 08:59
  • Joseph, I installed Code Contracts correctly. As you can see in my question, the Code Contracts work in general and just fail to work in the specific case mentioned above. – vlow Jan 15 '15 at 00:32