views:

108

answers:

2

I'm playing around with Microsoft's CodeContracts and encountered a problem I was unable to solve. I've got a class with two constructors:

public Foo (public float f) {
    Contracts.Require(f > 0);
}
public Foo (int i)
    : this ((float)i)
{}

The example is simplified. I don't know how to check the second constructor's f for being > 0. Is this even possible with Contracts?

+1  A: 

I would add a static Method that converts the int to the float and include the Contract.Requires in there.

    class Foo
{
    public Foo(float f)
    {
        Contract.Requires(f > 0);
    }
    public Foo(int i)
        : this(ToFloat(i))
    { }

    private static float ToFloat(int i)
    {
        Contract.Requires(i > 0);
        return i;
    }
}

Hope this helps.

Vapour in the Alley
+2  A: 

You can just add the precondition to the second constructor's body.

public TestClass(float f)
{
    Contract.Requires(f > 0);
    throw new Exception("foo");
}
public TestClass(int i): this((float)i)
{
    Contract.Requires(i > 0);
}

EDIT

Try calling the code above with:

TestClass test2 = new TestClass((int)-1);

You will see that the precondition is thrown before the regular Exception is thrown.

KoMet
I guess the line you added would be evaluated only after the float constructor has already been invoked, does it?
chiccodoro
@Chiccodoro: Actually, no. I've tested it to be sure, and if you would put a throw exception in the first constructor's body and call the second constructor with invalid input, Code Contracts would throw a Precondition failed("i > 0") before it would throw the exception from the first constructor.
KoMet
So, is that "Contract" feature a language extension rather than a library? Because normally the base class constructor is executed *before* the subclass constructor.
chiccodoro
Well, Code Contracts is not just a library that is normally executed. With Code Contracts disabled, nothing happens even if you do write contracts. When you enable it, Code Contracts 'rewrites' your code to inject the real checks.
KoMet