Как создать класс контракта для класса с требуемыми аргументами конструктора?

#c# #.net #code-contracts

#c# #.net #код-контракты

Вопрос:

У меня есть абстрактный класс, конструктору которого требуется параметр. Параметр не может быть нулевым.

 // the abstract class
[ContractClass(typeof(AbstractClassContract))]
public abstract class AbstractClass
{
   // Constructor with required parameter
   protected AbstractClass(SqlConnection connection)
   {
      Contract.Requires(connection != null);
      Connection = connection;
   }

   protected SqlConnection Connection { get; set; }

   public abstract string GetSomething();
}
 

Абстрактный класс имеет класс контракта для проверки предварительных / последующих условий для абстрактных членов.

 // the contract class
[ContractClassFor(typeof(AbstractClass))]
public abstract class AbstractClassContract
{
   public override string GetSomething()
   {
      Contract.Ensures(Contract.Result<string>() != null);
      return default(string);
   }
}
 

Приведенный выше код не компилируется из-за ошибки ‘AbstractClass’ не содержит конструктор, который принимает 0 аргументов.

Я могу добавить конструктор, как показано ниже, и код будет скомпилирован и, похоже, заработает.

    public AbstractClassContract(SqlConnection connection)
      : base(connection)
   { }
 

Но является ли это допустимым конструктором для класса контракта? Вызовет ли это проблему в какой-то ситуации? Меня беспокоит то, что параметр в конечном итоге требуется конструктору абстрактного класса.

Если это действительно так, то как .NET может обойти требуемое ограничение параметров?

Ответ №1:

Прошло некоторое время с тех пор, как я просматривал контракты кода, но я ожидал, что ваш класс contract на самом деле никогда не создавался. Вместо этого средство проверки контрактов в основном будет всасывать код из вашего класса contract в каждый конкретный подкласс.

Итак, если я пишу, ваш конструктор AbstractClassContract должен быть в порядке. Или вы могли бы просто использовать new SqlConnection("this is never called") , чтобы быть понятнее 🙂

Комментарии:

1. Вы правы — я использовал отладчик и подтвердил, что конструктор класса contract на самом деле никогда не вызывается. Проверки до / после выполнения условий из класса contract выполняются так, как если бы они были частью конкретного подкласса, как вы предложили (даже трассировка стека указывает на это). Итак, конструктор класса contract предназначен только для показа… Я предполагаю, чтобы сделать компилятор счастливым.