Ho pensato al metodo IEnumerator.Reset()
. Ho letto nella documentazione MSDN che esiste solo per l'interoperabilità COM. Come programmatore C++ mi sembra uno IEnumerator
che supporta Reset
è quello che chiamerei uno forward iterator, mentre uno IEnumerator
che non supporta Reset
è davvero un input iterator.Il C# trarrebbe vantaggio dalle distinzioni tra tipi di enumeratori, come gli iteratori C++?
Quindi una parte della mia domanda è, questa comprensione è corretta?
La seconda parte della mia domanda è, sarebbe di alcun beneficio in C# se ci fosse una distinzione tra iteratori di input e iteratori di inoltro (o "enumeratori" se si preferisce)? Non aiuterebbe a eliminare una certa confusione tra i programmatori, come quella trovata in questo SO question about cloning iterators?
MODIFICA: Chiarimento in avanti e iteratori di input. Un iteratore di input garantisce solo che è possibile enumerare i membri di una raccolta (o da una funzione generatore o un flusso di input) solo una volta. Questo è esattamente il modo in cui IEnumerator funziona in C#. Se è possibile enumerare o meno una seconda volta, viene determinato se è supportato o meno Reset
. Un iteratore diretto, non ha questa restrizione. Puoi enumerare i membri tutte le volte che vuoi.
Alcuni programmatori C# non sottostimano il motivo per cui un IEnumerator
non può essere utilizzato in modo affidabile in un algoritmo multipass. Si consideri il seguente caso:
void PrintContents(IEnumerator<int> xs)
{
while (iter.MoveNext())
Console.WriteLine(iter.Current);
iter.Reset();
while (iter.MoveNext())
Console.WriteLine(iter.Current);
}
Se chiamiamo PrintContents
in questo contesto, non è un problema:
List<int> ys = new List<int>() { 1, 2, 3 }
PrintContents(ys.GetEnumerator());
Tuttavia guardare il seguente:
IEnumerable<int> GenerateInts() {
System.Random rnd = new System.Random();
for (int i=0; i < 10; ++i)
yield return Rnd.Next();
}
PrintContents(GenerateInts());
Se il IEnumerator
supportato Reset
, in altre parole supportavano algoritmi multi-pass, quindi ogni volta che si ripeteva la raccolta sarebbe diverso. Questo sarebbe indesiderabile, perché sarebbe un comportamento sorprendente. Questo esempio è un po 'simulato, ma si verifica nel mondo reale (ad esempio la lettura dai flussi di file).
Penso che tu intenda "IEnumerator.Reset', non" IEnumerable .Reset ", giusto? –
Sì, grazie! Mi dispiace per quello – cdiggins
Interessante domanda. Ma forse dovresti spiegare il C++ - parla un po ', visto che molti programmatori C# vedranno questo. Potrebbe non essere ovvio quale sia un iteratore di input e un iteratore di inoltro, esattamente (in particolare, le capacità single/multipass di essi, che sono ciò che è veramente rilevante per questa domanda) – jalf