MoveNext()
を呼び出して次のコードブロックを実行できるので、列挙子とyieldキーワードを使用して非同期/互い違い操作を行うことができます。GCはIEnumeratorとどのように連携して処理されますか?
しかし、Enumeratorオブジェクトが何であるかは分かりません。列挙子のスコープを使用しているメモリはどこに行きますか?もしあなたがMoveNext()
列挙子を終わらせなければ、最終的にGCになるのでしょうか?
基本的に、私は潜在的に多くの列挙子を使用しているため、GCのヒット数を下げようとしています。特にUnityの古いバージョンのためにGCがUnity内部で問題になる可能性があります。
私はこれをプロファイルしようとしましたが、まだ私の頭を包み込むことはできません。私はEnumeratorsで起こるスコープ/参照を理解していません。また、結果として得られる関数から列挙子を作成するときに列挙子がオブジェクトとして作成されるかどうかはわかりません。
次の例では、より良い私の混乱を示しています
// 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?
コンパイラは、列挙子メソッドを書き換えて、コードを名前を変更できないクラスに移動します。このクラスは、ローカル変数がクラスのフィールドになるステートマシンを実装し、状態を失うことなくMoveNext()を再入力できるようにします。 IEnumeratorインターフェイスリファレンスは、実際にはそのクラスのオブジェクトへの参照です。あなたのコードがforeachループを離れるとすぐにGC-edになることができるように、参照が収集されると、すべてが存在しなくなります。 –
ハンスの言葉の例:http://goo.gl/fs4eNo – xanatos
よろしくお願いいたします。それは私がAT ALLを期待したことをしません。 これは、列挙子が従来の手段に比べてかなり重いことを意味しますか?私はGCをダウンさせようとしていますが、新しいEnumeratorを起動するたびに新しいゴミを作成するようです(そして多くの列挙子があります)。 – mGuv