Ich verstehe, dass Enumeratoren und das Yield-Schlüsselwort verwendet werden können, um mit asynchronen/gestaffelten Operationen zu helfen, wie Sie MoveNext()
aufrufen können, um den nächsten Codeblock auszuführen.Wie funktioniert GC mit IEnumerator und Ertrag?
Allerdings verstehe ich nicht wirklich, was dieses Enumerator-Objekt ist. Wohin geht der Speicher des Bereichs des Enumerators? Wenn Sie nicht einen Enumerator MoveNext()
tun, wird es schließlich GC'd?
Grundsätzlich versuche ich, meine GC-Treffer niedrig zu halten, da ich möglicherweise eine Menge von Enumerators und GC kann ein Problem in Unity sein, vor allem aufgrund der älteren Version von Mono verwendet.
Ich habe versucht, dies zu profilieren, kann aber meinen Kopf immer noch nicht um sie wickeln. Ich verstehe das Scoping/Referenzieren, das mit Enumerators passiert, nicht. Ich verstehe auch nicht, wenn Enumeratoren als Objekte erstellt werden, wenn Sie eine aus einer Funktion erstellen, die ergibt.
Das folgende Beispiel zeigt meine Verwirrung besser:
// Example enumerator
IEnumerator<bool> ExampleFunction()
{
SomeClass heavyObject = new SomeClass();
while(heavyObject.Process())
{
yield return true;
}
if(!heavyObject.Success)
{
yield return false;
}
// In this example, we'll never get here - what happens to the incomplete Enumerator
// When does heavyObject get GC'd?
heavyObject.DoSomeMoreStuff();
}
// example call - Where does this enumerator come from?
// Is something creating it with the new keyword in the background?
IEnumerator<bool> enumerator = ExampleFunction();
while(enumerator.MoveNext())
{
if(!enumerator.Current)
{
break;
}
}
// if enumerator is never used after this, does it get destroyed when the scope ends, or is it GC'd at a later date?
Der Compiler überschreibt Ihre Enumerator-Methode und verschiebt den Code in eine Klasse mit einem unsäglichen Namen. Diese Klasse implementiert eine Zustandsmaschine, bei der Ihre lokalen Variablen zu Feldern der Klasse werden, und ermöglicht, dass MoveNext() erneut eingegeben wird, ohne den Status zu verlieren. Die IEnumerator-Schnittstellenreferenz ist eigentlich eine Referenz auf ein Objekt dieser Klasse. Alles verschwindet, wenn diese Referenz erfasst wird. Sobald der Code die foreach-Schleife verlässt, ist er berechtigt, GC-ediert zu werden. –
Beispiel von dem, was Hans sagte: http://goo.gl/fs4eNo – xanatos
Okay, danke. Das tut nicht, was ich ALLES erwartete. Bedeutet das, Enumerators sind ziemlich schwer im Vergleich zu traditionellen Mitteln? Ich versuche, GC herunterzuhalten, aber es scheint, als würde ich immer neuen Müll erzeugen, wenn ich einen neuen Enumerator starte (und ich habe eine Menge Aufzählungen). – mGuv