由合同前提条件引起的IEnumerable多枚举

时间:2012-07-04 10:29:42

标签: c# .net ienumerable validation code-contracts

我有一个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,就像在原始示例中一样?如果没有,那么是否有人制定了良好的解决方案?

1 个答案:

答案 0 :(得分:7)

使用其中一种设计用于IEnumerable的方法,例如Contract.Exists

  

确定元素集合中的元素是否存在于函数中。

     

<强>返回

     

当且仅当谓词对集合中任何类型为T的元素返回true时才为true。

因此,您的谓词可以返回true


Contract.Requires(orderIds != null);
Contract.Requires(Contract.Exists(orderIds,a=>true));