Укажите код контракта по параметрам Func <T>? - PullRequest
5 голосов
/ 30 октября 2010

Скажите, что у меня есть следующее

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

Можно ли указать, что мои Func<T> параметры должны соответствовать некоторым контрактам?

Ответы [ 3 ]

2 голосов
/ 30 октября 2010

В общем, это кажется проблематичным требованием, так как вызов f может вызвать побочные эффекты, поэтому указание контракта может повлиять на то, что делает метод.

Как разработчик библиотеки Code Contracts, можно ввести код-обертку, который проверяет, соответствует ли значение f контракту, когда оно вызывается в контексте вашего метода (чтобы избежать введения ложного метода).вызов).Это проблематично по нескольким причинам:

  1. Этот метод может никогда не вызвать f, поэтому вызывающая сторона может нарушить контракт и не быть заблокированной.
  2. Метод может вызвать f только после выполнения какой-либо другой работы, которая может быть недействительной, учитывая, что вызов f не удовлетворяет спецификации.

Если бы у f не было побочных эффектов, тогда они не были быпроблемы, но при наличии побочных эффектов, связанных с 1, всегда вызывать f не сработает, а вызов f до выполнения какой-либо работы с 2 также не сработает.заключение Я не думаю, что это возможно (в контексте контрактов с нативным кодом) и по уважительной причине.

1 голос
/ 30 октября 2010

Если вы имеете в виду, что переданный метод должен проверить себя, например, параметр не является нулевым, нет, вы не можете сделать это. Контракты по-прежнему просто добавляют код в тело метода.

Однако вы можете заключить делегата в другой делегат, например:

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;
    };
}

Таким образом, вы можете сами вводить кодовые контракты.

0 голосов
/ 30 октября 2010

Если (как здесь) вас беспокоит именно недействительность, ReSharper (начиная с 4.0) имеет поддержку таких аннотаций, как CanBeNull и NotNull, которые могут быть размещены в качестве атрибутов в методах, после чего R # может предупредить о возможных нулевых операциях разыменования.

...