Donc, cette question vient d'être posée sur le SO:Quelqu'un peut-il s'il vous plaît expliquer ce code d'évaluation paresseux?
How to handle an "infinite" IEnumerable?
Mon exemple de code:
public static void Main(string[] args)
{
foreach (var item in Numbers().Take(10))
Console.WriteLine(item);
Console.ReadKey();
}
public static IEnumerable<int> Numbers()
{
int x = 0;
while (true)
yield return x++;
}
Quelqu'un peut-il s'il vous plaît expliquer pourquoi il en est paresseux évalué? J'ai recherché ce code dans Reflector, et je suis plus confus que quand j'ai commencé.
sorties réflecteur:
public static IEnumerable<int> Numbers()
{
return new <Numbers>d__0(-2);
}
Pour la méthode des nombres, et semble avoir généré un nouveau type pour cette expression:
[DebuggerHidden]
public <Numbers>d__0(int <>1__state)
{
this.<>1__state = <>1__state;
this.<>l__initialThreadId = Thread.CurrentThread.ManagedThreadId;
}
Cela n'a aucun sens pour moi. J'aurais supposé que c'était une boucle infinie jusqu'à ce que je mette ce code ensemble et l'ai exécuté moi-même.
EDIT: Je comprends maintenant que .Take() peut dire foreach que l'énumération est « terminée », quand il a vraiment pas, mais ne devrait pas les numéros() être appelé dans son intégralité avant enchaînant transmettre à la prise()? Le résultat de Take est ce qui est réellement énuméré, correct? Mais comment est-ce que Take s'exécute quand Numbers n'a pas complètement évalué?
EDIT2: Alors est-ce juste une astuce de compilateur spécifique imposée par le mot-clé 'yield'?
Oui, mais Numbers() lui-même ne devrait-il pas être entièrement évalué afin de continuer avec Take Call? Je comprends que Numbers lui-même est une boucle infinie. Pourquoi l'ajout de .Take() arrête-t-il soudainement les nombres d'être évalués dans leur intégralité? – Tejs
Intéressant. Merci pour le lien! Cette question (et le code) m'a fait faire une double prise, et je réalise maintenant que j'ai plus à apprendre sur Enumerables! – Tejs