IEnumerable множественное перечисление, вызванное предварительным условием контракта

У меня есть параметр IEnumerable, который должен быть непустым. Если есть предварительное условие, подобное приведенному ниже, тогда коллекция будет перечисляться во время этого. Но в следующий раз я буду ссылаться на него. (A "Возможное множественное перечисление IEnumerable" предупреждение в Resharper.)

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.

Есть ли решение, которое работает с кодовыми контрактами и IEnumerables, как в исходном примере? Если нет, то кто-то разработал хороший образец для работы вокруг него?

Ответ 1

Используйте один из методов, предназначенных для работы с IEnumerable s, например Contract.Exists:

Определяет, существует ли элемент внутри коллекции элементов внутри функции.

Возвращает

true тогда и только тогда, когда предикат возвращает true для любого элемента типа T в коллекции.

Таким образом, ваш предикат мог бы просто вернуть true.


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