views:

98

answers:

3

Say I have the following

public T Example(Func<T> f)
{
     Contract.Requires(f != null);
     Contract.Requires(f() != null); // no surprise, this is an error
...
}

Is there any way to specify that my Func<T> parameters must obey some contracts?

+1  A: 

If you mean that the passed method should check itself whether e.g. the parameter is not null, no you cannot do this. Contracts still simply add code to the method body.

What you can however do is wrap the delegate into a different delegate, e.g.:

public T Example<T, TResult>(Func<T, TResult> f)
    where T : class
    where TResult : class
{
    Contract.Requires(f != null);

    f = WrapWithContracts(f);

    // ...
}

private Func<T, TResult> WrapWithContracts<T, TResult>(Func<T, TResult> f)
    where T : class
    where TResult : class
{
    return p =>
    {
        Contract.Requires(p != null);
        Contract.Ensures(Contract.Result<TResult>() != null);

        var result = f(p);

        return result;
    };
}

This way you can introduce code contracts yourself.

Pieter
Updated to include a postcondition for the return value.
Pieter
I’ve taken the liberty to fix the contract syntax. (You have to have all the contracts at the top of the method, and you have to use `Contract.Result<T>()` for the method’s return value.)
Timwi
@Timwi - Thanks. I have no experience with `Contract` s so your help is very welcome :).
Pieter
I think this is a little dangerous. The point of code contracts is to specify contracts that *always* hold... and you don't know anything about `f`'s behavior. In particular, the `Ensures` might not hold (and the static checker will tell you this - it requires an `Assume` to get it to stop warning). *Yes*, if runtime contract checking is enabled, then the `Ensures` will catch this, so your other code that depends on this requirement won't be run, but at that point it's a little late because a non-catchable exception has been thrown! :)
Porges
+2  A: 

In general, that seems like a problematic requirement since invoking f may introduce side effects so specifying a contract could affect what the method does.

As the implementer of the Code Contracts library one could introduce wrapper code that checks to see if the value of f obeys the contract when it is invoked in the context of your method (to avoid introducing a spurious method call). This is problematic for a couple of reasons:

  1. The method might never invoke f, so the caller could violate the contract and not get busted.
  2. The method could call f only after doing some other work which might be invalid given that the call to f didn't satisfy the specification.

If f had no side effects then these wouldn't be problems, but in the presence of side effects dealing with 1 by always calling f wouldn't work and calling f before doing any work to deal with 2 also wouldn't fly.

So, in conclusion I don't think that this is possible (in the context of native code contracts) and with good reason.

Cole
I believe the team are considering several options, such as something along the lines of a `Pure` attribute for `Func` parameters. It doesn't appear to be arriving any time soon, though.
Porges
A: 

If (as here) it's specifically nullity you're concerned with, ReSharper (from 4.0 onwards) has support for Annotations such as CanBeNull and NotNull, which can be placed as attributes on methods, after which R# can warn about possible null dereferencing operations.

AakashM