Неудобное использование Contract.ValueAtReturn () - PullRequest
1 голос
/ 06 мая 2010

Я разрабатываю метод, который добавит элемент во внутренний список. Структура класса выглядит примерно так:

class MyCustomerDatabase {
    private IList<Customer> _customers = new List<Customer>();

    public int NumberOfCustomers { get { return _customers; } }    

    public void AddCustomer(Customer customer) {
        _customers.Add(customer);
    }
}

Теперь я подумывал добавить Contract.Ensures() о размере _клиентов, растущих на 1 с этим вызовом. Проблема в том, что я получаю странный код:

public void AddCustomer(Customer customer) {
    int numberOfCustomersAtReturn;
    Contract.Ensures(Contract.ValueAtReturn<int>(out numberOfCustomersAtReturn) == 
Contract.OldValue<int>(NumberOfCustomers) + 1);


    _customers.Add(customer);
    numberOfCustomersAtReturn = NumberOfCustomers;
}

Основная проблема заключается в том, что свойства на самом деле являются методами, поэтому вы не можете просто ссылаться на них при использовании Contract.ValueAtReturn(), поскольку его единственный параметр принимает переменные как out. Ситуация становится еще более странной, если я хочу добиться того же, но на этот раз с методом, который должен возвращать значение:

public int MyReturningMethod() {
    ...
   return abc(); //abc will add by one the number of customers in list
}
//gets converted to
public int MyReturningMethod() {
    int numberOfCustomersAtReturn;
    Contract.Ensures(Contract.ValueAtReturn<int>(out numberOfCustomersAtReturn) == Contract.OldValue<int>(NumberOfCustomers) + 1);

    int returnValue = abc();
    numberOfCustomersAtReturn = NumberOfCustomers;
    return returnValue;
}

Это кажется довольно неуклюжим :(

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

Спасибо

Ответы [ 2 ]

1 голос
/ 10 мая 2010

Кажется, что вы слишком усложняете вещи без причины. ValueAtReturn используется, чтобы говорить о out параметрах метода, и ничего больше & mdash; и у вас нет out параметров!

То, что вы ищете, это OldValue.

Предполагая, что эта строка:

public int NumberOfCustomers { get { return _customers; } }   

означает:

public int NumberOfCustomers { get { return _customers.Count; } }

Все, что вам нужно сделать, это:

class MyCustomerDatabase
{
    private readonly IList<Customer> customers = new List<Customer>();

    public int NumberOfCustomers { get { return customers.Count; } }

    public void AddCustomer(Customer customer)
    {
        Contract.Ensures(NumberOfCustomers ==
                         Contract.OldValue(NumberOfCustomers) + 1);

        customers.Add(customer);
    }
}

Статическая проверка может доказать это очень хорошо, благодаря постусловиям в IList<T>:)

1 голос
/ 06 мая 2010

Я думаю, вы все делаете правильно.

Хотя у меня такое чувство, что вы доводите контракты до крайности, описывая точные выходные последствия вызова этого метода. Imho, основная идея контрактов заключалась в том, чтобы обеспечить basic гарантии, такие как положительный результат, возвращение значения вообще и т. Д.

...