He estado pensando en el método IEnumerator.Reset()
. Leí en la documentación de MSDN que solo estaba allí para la interoperabilidad COM. Como un programador de C++ me parece como un IEnumerator
que admite Reset
es lo que yo llamaría forward iterator, mientras que un IEnumerator
que no admite Reset
es realmente un input iterator.¿Se beneficiaría C# de las distinciones entre tipos de enumeradores, como los iteradores de C++?
Así que la primera pregunta es: ¿es correcto este entendimiento?
La segunda parte de mi pregunta es, ¿sería beneficioso para C# si hubiera una distinción entre los iteradores de entrada y los iteradores directos (o "enumeradores" si lo prefiere)? ¿No ayudaría a eliminar la confusión entre los programadores, como la que se encuentra en este SO question about cloning iterators?
EDIT: aclaración en los iteradores de entrada y entrada. Un iterador de entrada solo garantiza que puede enumerar los miembros de una colección (o de una función de generador o una secuencia de entrada) solo una vez. Así es exactamente como funciona IEnumerator en C#. Si puede o no enumerar por segunda vez, está determinado por si se admite Reset
o no. Un iterador directo, no tiene esta restricción. Puede enumerar a los miembros tantas veces como desee.
Algunos programadores de C# no reparan por qué un IEnumerator
no se puede usar de manera confiable en un algoritmo multipaso. Considere el siguiente caso:
void PrintContents(IEnumerator<int> xs)
{
while (iter.MoveNext())
Console.WriteLine(iter.Current);
iter.Reset();
while (iter.MoveNext())
Console.WriteLine(iter.Current);
}
Si llamamos PrintContents
en este contexto, no hay problema:
List<int> ys = new List<int>() { 1, 2, 3 }
PrintContents(ys.GetEnumerator());
Sin embargo mira el siguiente:
IEnumerable<int> GenerateInts() {
System.Random rnd = new System.Random();
for (int i=0; i < 10; ++i)
yield return Rnd.Next();
}
PrintContents(GenerateInts());
Si el IEnumerator
apoyaron Reset
, en otras palabras admitían algoritmos de paso múltiple, luego cada iteración sobre la colección sería diferente. Esto sería indeseable, porque sería un comportamiento sorprendente. Este ejemplo es un poco falso, pero ocurre en el mundo real (por ejemplo, leyendo flujos de archivos).
Creo que te refieres a 'IEnumerator.Reset', no' IEnumerable .Reset', ¿verdad? –
¡Sí, gracias! Lo siento por eso. – cdiggins
Interesante pregunta. Pero tal vez deberías explicar el C++, hablar un poco, ya que muchos programadores de C# van a ver esto. Puede no ser obvio qué es un iterador de entrada y un iterador directo exactamente (en particular, las capacidades de uno/varios pasos de ellos, que son lo que realmente es relevante para esta pregunta) – jalf