Primero considere esto:
IEnumerable<T> current = new List<T>();
foreach (IOperation<T> operation in operations)
{
current = operation.Execute(current);
}
Este código parece estar creando enumerables anidados, cada uno de los cuales toma elementos de la anterior, se aplica alguna operación a ellos, y pasa el resultado a la siguiente. Pero solo construye los enumerables. Nada realmente sucede todavía. Está listo para funcionar, almacenado en la variable current
. Hay muchas formas de implementar IOperation.Execute
, pero podría ser algo como esto.
IEnumerable<T> Execute(IEnumerable<T> ts)
{
foreach (T t in ts)
yield return this.operation(t); // Perform some operation on t.
}
Otra opción que se sugiere en el artículo es una especie:
IEnumerable<T> Execute(IEnumerable<T> ts)
{
// Thank-you LINQ!
// This was 10 lines of non-LINQ code in the original article.
return ts.OrderBy(t => t.Foo);
}
Ahora mira esto:
IEnumerator<T> enumerator = current.GetEnumerator();
while (enumerator.MoveNext());
En realidad, esto hace que la cadena de operaciones a realizar. Cuando los elementos se solicitan de la enumeración, hace que los elementos del enumerable original pasen a través de la cadena IOperations
, cada uno de los cuales realiza alguna operación en ellos. El resultado final se descarta, por lo que solo el efecto secundario de la operación es interesante, como escribir en la consola o iniciar sesión en un archivo. Esto habría sido una manera más sencilla de escribir las dos últimas líneas:
foreach (T t in current) {}
Otra cosa a observar es que la lista inicial que comienza el proceso es una lista vacía por lo que para que esto tenga sentido algunos casos de T tienen que ser creado dentro de la primera operación. En el artículo, esto se hace pidiendo al usuario que ingrese desde la consola.
No se puede ver ningún propósito. Si hay algún efecto secundario oculto para llamar a MoveNext en este contexto, esa es una pieza desagradable de código. –