短い答え、いいえ、o
は解放されます。ご心配なく。
少し長い答え:
をあなたのコードは、多かれ少なかれ、次ん:
- 新しいMyClassの(
o
)への参照のためにそのスレッド上でいくつかのローカルストレージを作成します。
- 新しいMyClassを作成
- 新しいMyClassへの参照を
o
に保存します。
- ラムダから新しいデリゲートを作成します。
- イベントにデリゲートを割り当てます(
o
にはデリゲートへの参照が含まれています)。
この間に、GCはスレッドを停止して、どのオブジェクトがルートされているかどうかを調べることがあります。ルートは、スタティックまたはスレッドのローカル記憶域にあるオブジェクトです(これは、基本的に静的な形式のスレッド・ローカル・ストレージではなく、スタックによって実装された特定のスレッドの実行におけるローカル変数を意味します)。ルーテッドオブジェクトは、ルーツ、それらによって参照されるオブジェクト、それらによって参照されるオブジェクトなどです。根っこのオブジェクトは収集されません。残っているオブジェクトは、現在は無視されるファイナライザーとは関係ありません。
MyClassオブジェクトが作成された後も、スレッドのローカルストレージによってルートされていません。
デリゲートオブジェクトが作成された後は、スレッドのローカルストレージによってルートされていないか、またはその参照を持つMyClassによってルートされていません。
次に、次に何が起こりますか?
によって異なります。ラムダはMyClassを生かし続けることはありません(MyClassはそれを生かしていますが、MyClassが行くとラムダもそうです)。これは "Will 'o'がガベージコレクションの対象になると答えるだけでは不十分です。しかし、。
void Meth0()
{
var o = new MyClass();
o.MyClassEvent += (args) => {};
}//o is likely eligible for collection, though it doesn't have to be.
void Meth1()
{
int i = 0;
{
var o = new MyClass();
o.MyClassEvent += (args) => {};
}//o is likely not eligible for collection, though it could be.
while(i > 100000000);//just wasting time
}
void Meth2()
{
{
var o = new MyClass();
o.MyClassEvent += (args) => {};
int i = 0;//o is likely eligible for collection, though it doesn't have to be.
while(i > 100000000);//just wasting time
}
}
void Meth3()
{
{
var o = new MyClass();
o.MyClassEvent += (args) => {};
var x0 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x1 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x2 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x3 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x4 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x5 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x6 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x7 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x8 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x9 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x10 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
var x11 = new MyClass();//o is even more likely eligible for collection, though it doesn't have to be.
int i = 0;
while(i > 100000000);//just wasting time
}
}
Meth0は一見もっともシンプルですが、実際にはそうではありませんので、ここで再び取り上げます。 Meth1で
、実装はそうo
がスコープではありませんが、実装はまだ使用されているローカルストレージを持っていますので、それは、もはや必要とされていないので、それは、あるとしてローカルストレージを残すべきです。 Meth2で
、実装は「スコープ内」(それがスコープ内にまだあるにもかかわらず、収集する資格があるのでi
ことがo
のために使用したのと同じローカル・ストレージを使用することができ、プログラマが行うことを選択できることを意味それと何か、しかし彼または彼女はそうしなかったし、コンパイルされたコードはそのような概念を必要としない)。
Meth3はストレージを再利用する可能性が高くなります。これは、一時的に使用されるため、すべてのストレージを先に設定するのではなく、より意味があるためです。
これらのものはありませんはこのようになるととなります。 Meth2とMeth3はどちらも、最初にこのメソッドに必要なすべてのストレージを確保することができます。メッシュ1は、i
とo
の順番を変更することに違いがないため、ストレージを再利用できます。
Meth0は、呼び出し元のメソッドが次にローカルストレージを使用するかどうかに依存する可能性があるため、より複雑です(どちらも正当な実装です)。 IIRCでは、現在の実装では常にクリーンアップが行われていますが、わかりませんが、とにかく問題はありません。
スコープは関連するものではなく、コンパイラとそれ以降のJITterがオブジェクトに関連するローカルストレージを使用できるかどうかを示します。メソッドやプロパティが呼び出される前にオブジェクトをクリーンアップすることもできます(オブジェクトが削除されてもうまくいくので、メソッドとプロパティがthis
やオブジェクトのフィールドのいずれかを使用しない場合) )。
これはGCに適しているはずです。私はこれを答えにするのに十分ではない。 –
これは、他の関数(ラムダなど)をイベントにサブスクライブするのと違って動作する理由はわかりません。だから私はティムに同意する。 –
[イベント処理に匿名の代理人を使用する場合のガベージコレクション]の可能な複製(http://stackoverflow.com/questions/371109/garbage-collection-when-using-anonymous-delegates-for-event-handling) –