Я разрабатываю метод, который добавит элемент к внутреннему списку. Структура класса - что-то вроде:
class MyCustomerDatabase {
private IList<Customer> _customers = new List<Customer>();
public int NumberOfCustomers { get { return _customers; } }
public void AddCustomer(Customer customer) {
_customers.Add(customer);
}
}
Теперь, я думал о добавлении a Contract.Ensures()
о размере _customers, растущего на 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;
}
Основная проблема состоит в том, что свойства являются на самом деле методами, таким образом, Вы не можете просто сослаться на них direcly при использовании 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;
}
Это кажется довольно неуклюжим :(
Контракты кода должны иметь целью получать более ясные вещи, и это кажется правильным противоположное. Я делаю что-то не так?
Спасибо
Кажется, что вы переусложняете вещи без причины. ValueAtReturn
используется для обсуждения out
параметров метода, и ничего больше - а у вас нет никаких 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
:)
Думаю, вы все делаете правильно.
Хотя мне кажется, что вы доводите Contracts до крайности, описывая точные последствия вызова этого метода для вывода. Imho основная идея контрактов заключалась в том, чтобы гарантировать базовые гарантии, такие как положительные, вообще возвращающие значение и так далее.