Tengo un parámetro IEnumerable
que se requiere que no esté vacío. Si hay una precondición como la siguiente, la colección se enumerará durante el mismo. Pero se enumerará nuevamente la próxima vez que lo haga referencia. (Una "posible enumeración múltiplo de IEnumerable" de advertencia en ReSharper.)Enumerable enumeración múltiple causada por la condición previa del contrato
void ProcessOrders(IEnumerable<int> orderIds)
{
Contract.Requires((orderIds != null) && orderIds.Any()); // enumerates the collection
// BAD: collection enumerated again
foreach (var i in orderIds) { /* ... */ }
}
Estas soluciones hechas ReSharper feliz, pero no se compilará:
// 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());
Hay otras soluciones que serían válidas, pero tal vez no siempre es ideal como usar ICollection o IList, o realizar una típica excepción de tiro nulo.
¿Existe alguna solución que funcione con contratos de código e IEnumerables como en el ejemplo original? Si no, ¿alguien ha desarrollado un buen patrón para solucionarlo?
Creo que es probable que sólo una mala idea tener un contrato depende de un IEnumerable - como IEnumerables, por definición, puede incurrir en efectos secundarios. –
Hasta ahora he usado ICollection como una solución alternativa y nunca tuve un problema, aunque tengo curiosidad por si hay una solución para IEnumerables. – Keith