我正在设计一个将元素添加到内部列表的方法。该类的结构类似于:
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()
,大约相当于_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;
}
主要问题是属性实际上是方法,因此在使用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;
}
这看起来很笨拙:(
代码合同应该旨在让事情变得更加清晰,而这恰恰相反。我做错了吗?
由于
答案 0 :(得分:1)
我认为你做的一切都是正确的。
Altough我觉得你通过描述调用该方法的确切输出含义来将Contracts置于极端。 Imho合同的基本思想更多是为了确保 基本 保证,如积极的,完全返回一个值,等等。
答案 1 :(得分:1)
似乎你无缘无故地过度复杂化了。 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<T>
中的后置条件:)