So wurde diese Frage nur so fragte auf:Kann jemand bitte diesen faulen Bewertungscode erklären?
How to handle an "infinite" IEnumerable?
Mein Beispielcode:
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++;
}
Kann jemand bitte erklären, warum diese faul ausgewertet? Ich habe diesen Code in Reflector nachgeschlagen, und ich bin mehr verwirrt als zu Beginn.
Reflector Ausgänge:
public static IEnumerable<int> Numbers()
{
return new <Numbers>d__0(-2);
}
Für die Zahlen Methode und sieht eine neue Art haben für diesen Ausdruck erzeugt:
[DebuggerHidden]
public <Numbers>d__0(int <>1__state)
{
this.<>1__state = <>1__state;
this.<>l__initialThreadId = Thread.CurrentThread.ManagedThreadId;
}
Das macht mir keinen Sinn. Ich hätte angenommen, dass es eine Endlosschleife war, bis ich diesen Code zusammenstellte und ihn selbst ausführte.
EDIT: Also ich verstehe jetzt, dass .Nehmen() kann dem foreach sagt, dass die Aufzählung ‚beendet‘ hat, wenn es wirklich nicht hat, soll aber nicht Zahlen() aufgerufen wird in seiner Gesamtheit vor Verkettungs Vorwärts zum Take()? Das Take-Ergebnis ist das, was tatsächlich überzählt wird, richtig? Aber wie wird Take ausgeführt, wenn Numbers nicht vollständig ausgewertet wurde?
EDIT2: Ist dies also nur ein spezifischer Compiler-Trick, der durch das Schlüsselwort 'yield' erzwungen wird?
Ja, aber würde Numbers() selbst nicht vollständig ausgewertet werden müssen, um mit dem Take Call fortzufahren? Ich verstehe, dass Numbers selbst eine Endlosschleife ist. Warum verhindert das Hinzufügen von .Take() plötzlich, dass Numbers in seiner Gesamtheit ausgewertet wird? – Tejs
Interessant. Danke für den Link! Diese Frage (und der Code) hat mich dazu gebracht, einen Doppelklick zu machen, und mir ist jetzt klar, dass ich mehr über Enumerables erfahren muss! – Tejs