Ocasionalmente me encuentro en la situación de tener que procesar un enumerable varias veces. Si la enumeración es costosa, no repetible y arroja una gran cantidad de datos (como un IQueryable que se lee desde una base de datos), enumerar varias veces no es una opción, ni almacenar el resultado en la memoria.
Hasta hoy a menudo terminaba escribiendo clases de agregador en las que podía insertar elementos en un ciclo foreach y eventualmente leer los resultados, mucho menos elegante que LINQ.
Pero espera, acabo de decir "push"? ¿No suena como ... reactivo? Así que estaba pensando en la caminata de esta noche. De vuelta a casa, lo probé, ¡y funciona!
El fragmento de ejemplo muestra cómo obtener tanto el artículo en su mínimo y máximo de una secuencia de números enteros en una sola pasada, utilizando operadores LINQ estándar (las de Rx, que es):
public static MinMax GetMinMax(IEnumerable<int> source)
{
// convert source to an observable that does not enumerate (yet) when subscribed to
var connectable = source.ToObservable(Scheduler.Immediate).Publish();
// set up multiple consumers
var minimum = connectable.Min();
var maximum = connectable.Max();
// combine into final result
var final = minimum.CombineLatest(maximum, (min, max) => new MinMax { Min = min, Max = max });
// make final subscribe to consumers, which in turn subscribe to the connectable observable
var resultAsync = final.GetAwaiter();
// now that everybody is listening, enumerate!
connectable.Connect();
// result available now
return resultAsync.GetResult();
}
esto no es una responder a la pregunta, que era "¿Está bien llamar a los métodos de Linq en IEnumerable más de una vez?" ... la respuesta es no". –
Bueno, lo que "OK" significa es un poco confuso. Puede iterar sobre una lista cuantas veces quiera. Menciono las ramificaciones de esto en mi respuesta. ¿Cómo no está bien iterar sobre ellos? Publique su propia respuesta si lo cree (aunque ya hay una respuesta aceptada). –
Está perfectamente claro. 'items' es un IEnumerable, no una lista, y solo puede atravesarlo una vez. No es necesario publicar otra respuesta, pero es importante que los lectores entiendan que esta es incorrecta y que ni siquiera toca la pregunta. –