Повторять кодовые требования контракта вниз по цепочке наследования?
Предположим, у вас уже есть крупный проект, и вы хотите интегрировать в него контракты по коду. В существующем коде используется логика if-null-then-throw. Для заданных условий в документации предлагается установить режим сборки на Custom Validation Validation.
У меня есть следующие классы:
class A
{
protected virtual void Foo(int a, int b)
{
if (a == null)
throw new ArgumentNullException(a);
if (b == null)
throw new ArgumentNullException(b);
Contract.EndContractBlock();
}
}
class B : A
{
protected override void Foo (int a, int b)
{
// some stuff
base.Foo(a, b);
}
}
Когда я компилирую, я получаю следующее предупреждение:
предупреждение CC1055: метод "B.Foo(int, int)" должен содержать пользовательскую проверку аргумента для "Requires(a!= null)", так как он переопределяет "A.Foo(int,int)", что предполагает его. Если вы не хотите использовать пользовательскую проверку аргументов в этой сборке, измените режим сборки на "Требуется стандартный контракт".
Я не хочу повторять предварительные условия для каждого переопределенного метода! Есть ли способ обойти это?
1 ответ
Работает нормально, если вы используете Contract.Requires()
вместо Contract.EndContractBlock()
,
В руководстве, приведенном ниже, есть раздел, в котором предлагается добавить [SuppressMessage]
атрибут переопределения метода.
Из руководства пользователя Code Contracts стр.22 раздел 5.2.3.
Делегирование проверок другим методам
Предположим, у вас есть шаблон кода, похожий на следующий код:
public class Base { public virtual void Compute(string data) { if (data == null) throw new ArgumentNullException(...); Contract.EndContractBlock(); ... } } public class Derived : Base { public override void Compute(string data) { base.Compute(data); ... } }
Затем утилита выдаст предупреждение CC1055 с сообщением вида:
Метод "Derived.Compute" должен содержать пользовательскую проверку аргумента для "Requires (ArgumentNullException)(data! = Null)", так как он переопределяет "Base.Compute", что и предполагает.
В этой ситуации предупреждение не помогает, так как реализация Derived.Compute делегирует проверку параметра другому методу (в данном случае базовому методу). Чтобы избежать предупреждения в этой ситуации без повторения проверки, вы можете добавить атрибут SuppressMessage к методу:
public class Derived : Base { [SuppressMessage("Microsoft.Contracts", "CC1055", Justification = "Validation performed in base method")] public override void Compute(string data) { base.Compute(data); ... } }