Search code examples
c#.netienumerablevalidationcode-contracts

IEnumerable multiple enumeration caused by contract precondition


I have an IEnumerable parameter that is required to be non-empty. If there's a precondition like the one below then the collection will be enumerated during it. But it will be enumerated again the next time I reference it, thereby causing a "Possible multiple enumeration of IEnumerable" warning in Resharper.

void ProcessOrders(IEnumerable<int> orderIds)
{
    Contract.Requires((orderIds != null) && orderIds.Any());  // enumerates the collection

    // BAD: collection enumerated again
    foreach (var i in orderIds) { /* ... */ }
}

These workarounds made Resharper happy but wouldn't compile:

// 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());

There are other workarounds that would be valid but maybe not always ideal like using ICollection or IList, or performing a typical if-null-throw-exception.

Is there a solution that works with code contracts and IEnumerables like in the original example? If not then has someone developed a good pattern for working around it?


Solution

  • Use one of the methods designed to work with IEnumerables, such as Contract.Exists:

    Determines whether an element within a collection of elements exists within a function.

    Returns

    true if and only if predicate returns true for any element of type T in collection.

    So your predicate could just return true.


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