Код контрактов на автоматически реализованные свойства - PullRequest
13 голосов
/ 01 апреля 2011

Есть ли способ заключить контракты на автоматически реализованные свойства в .NET? (А как, если ответ «Да»)?

(я предполагаю использовать контракты кода .NET от DevLabs)

Ответы [ 3 ]

16 голосов
/ 19 сентября 2013

Да, это возможно - все, что нужно, это добавить условие вашего контракта к методу [ContractInvariantMethod] в вашем классе, который затем добавляет эквивалентное предварительное условие Requires к автоматическому set ter и условие публикации Ensures добавляется к get. Из раздела 2.3.1 Ссылка

Как показывает пример, инварианты авто-свойств превращаются в:

  1. Предварительное условие для сеттера
  2. Постусловие для геттера
  3. Инвариант для базового базового поля

И к примеру:

public int MyProperty { get; private set ;}

[ContractInvariantMethod]
private void ObjectInvariant ()
{
  Contract.Invariant ( this.MyProperty >= 0 );
}

"Эквивалентно следующему коду:"

private int backingFieldForMyProperty;
public int MyProperty 
{
  get 
  {
    Contract.Ensures(Contract.Result<int>() >= 0);
    return this.backingFieldForMyProperty;
  }

  private set 
  {
    Contract.Requires(value >= 0);
    this.backingFieldForMyProperty = value;
  }
}

[ContractInvariantMethod]
private void ObjectInvariant () 
{
  Contract.Invariant ( this.backingFieldForMyProperty >= 0 );
...
1 голос
/ 18 апреля 2011

Спасибо, Поргес.

Моя ошибка заключалась в том, что я фактически использовал опцию ReleaseRequires, которая, действительно, имеет дело только с универсальной версией метода, Requires<T>.

Инвариант, который накладывается на автоматически реализуемое свойство, действительно превратился в предусловие Requires, но он не является универсальным - поэтому он не работал с этой опцией.

Что делать:

  • VARIANT 1. Рассмотрите возможность использования фрагментов кода и красивых Requires<T> вместо автоматически реализуемых свойств - что позволяет нам использовать исключения желаемого типа.

  • VARIANT 2. Измените параметр ReleaseRequires на Preconditions в опциях Code Contracts и не стесняйтесь писать инварианты в авто-свойствах - инструмент перезаписи автоматически изменитсяих в Requires.Тем не менее, они будут не универсальными - это означает, что в случае разрыва контракта будет брошено ContractException, и изменить его поведение невозможно.

Спасибо всем запомощь!

1 голос
/ 01 апреля 2011

Я думаю, нет, но вы могли бы легко написать фрагмент, который бы сделал это.Если вы пойдете по этому пути, - это бесплатный редактор фрагментов , который сделает задачу очень простой.

...