我有一个IEnumerable
参数,必须是非空的。如果有一个前提条件,如下面的那个,那么集合将在它期间枚举。但是下次我引用时会再次列举它。 (Resharper中的“可能多次枚举IEnumerable”警告。)
void ProcessOrders(IEnumerable<int> orderIds)
{
Contract.Requires((orderIds != null) && orderIds.Any()); // enumerates the collection
// BAD: collection enumerated again
foreach (var i in orderIds) { /* ... */ }
}
这些解决方法让Resharper高兴但不会编译:
// enumerating before the precondition causes error "Malformed contract. Found Requires
orderIds = orderIds.ToList();
Contract.Requires((orderIds != null) && orderIds.Any());
---
// enumerating during the precondition causes the same error
Contract.Requires((orderIds != null) && (orderIds = orderIds.ToList()).Any());
还有其他一些有效但可能并不总是理想的解决方法,例如使用ICollection或IList,或者执行典型的if-null-throw-exception。
是否有一个解决方案适用于代码契约和IEnumerables,就像在原始示例中一样?如果没有,那么是否有人制定了良好的解决方案?
答案 0 :(得分:7)
使用其中一种设计用于IEnumerable
的方法,例如Contract.Exists
:
确定元素集合中的元素是否存在于函数中。
<强>返回强>
当且仅当谓词对集合中任何类型为T的元素返回true时才为true。
因此,您的谓词可以返回true
。
Contract.Requires(orderIds != null);
Contract.Requires(Contract.Exists(orderIds,a=>true));