Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Specify code contract on Func<T> parameters?

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?

like image 674
Scott Weinstein Avatar asked Oct 25 '22 03:10

Scott Weinstein


2 Answers

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.

like image 50
mrmcgreg Avatar answered Nov 15 '22 06:11

mrmcgreg


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.

like image 33
Pieter van Ginkel Avatar answered Nov 15 '22 06:11

Pieter van Ginkel