Search code examples
c#.netdelegatescode-contracts

Code Contracts: ensure constraint on delegate to avoid "requires unproven" warning?


I have a class which allows a switch-like statement using any object type T and allows specifying a return type R. When I try to require non-null values I receive a warning that it requires unproven: value != null. Figured an Assume would take away the warning of the static checker but enforce it in runtime, but it does not do the former. What are my options?

Here is the class with the Contract.Requires statement:

public class SwitchReturn<T, R>
{
    public SwitchReturn(T o)
    {
        Contract.Requires(o != null);

        Object = o;
    }

    public T Object { get; private set; }
    public bool HasValue { get; private set; }
    public R Value { get; private set; }

    public void Set(R value)
    {
        Contract.Requires(value != null); // <== the source of all the troubles

        Value = value;
        HasValue = true;
    }
}

Here is an example of calling code with an unproven requires:

public static SwitchReturn<T, R> Case<T, R>(this SwitchReturn<T, R> s, Func<T, R> f)
{
    Contract.Requires(s != null);
    Contract.Requires(s.Object != null);
    Contract.Requires(f != null);

    if (!s.HasValue)
    {
        Contract.Assume(f(s.Object) != null); // <== does not remove the warning
        s.Set(f(s.Object)); // <== this is the cause of the warning
    }

    return s;
}

I would not want to remove the non-null requirement. Can a constraint be placed on the FUNC parameter that it ensures it does not return nulls?


Solution

  • f is not known to be pure. Calling it twice may give different results, so assuming that the first result is non-null says nothing about the second result.

    You should be able to store the result in a variable, add an assumption about that variable, and then pass that to your other method.

    if (!s.HasValue)
    {
        var val = f(s.Object);
        Contract.Assume(val != null);
        s.Set(val);
    }