namespace Test
{
class Test
{
delegate void HandleMessage(string message);
public void handleMessage(string message){}
static void Main(string[] args)
{
HandleMessage listener1 = new Test().handleMessage;
WeakReference w1 = new WeakReference(listener1);
HandleMessage listener2 = (message) => { };
WeakReference w2 = new WeakReference(listener2);
Console.WriteLine("w1.Target:\t[" + w1.Target + "]");
Console.WriteLine("w2.Target:\t[" + w2.Target + "]");
listener1 = null;
listener2 = null;
GC.Collect();
Console.WriteLine("after GC");
Console.WriteLine("w1.Target:\t[" + w1.Target + "]");
Console.WriteLine("w2.Target:\t[" + w2.Target + "]");
Console.ReadLine();
}
}
}
GC後にw2.Targetがnullにならないのはなぜですか?
w1.Target:[Test.Test + HandleMessage] w2.Target:[Test.Test + HandleMessage] GC後 w1.Target:[] w2.Target:[Test.Test + HandleMessage]
編集
すべての答えに感謝します、ブライアン・ラスムッセンとジョン・スキートあなたの答えは正しいです。今、私は何が起こっているのかを完全に理解しているので、すべてをより明確にするために別の例を書きました。
次の例は、次のことを示しています。
Test#create()がインスタンスのプロパティやメソッドを参照しない場合、Jon Skeetが言ったように、「private static HandleMessage CS $ <> 9__CachedAnonymousMethodDelegate1」がコンパイラによって作成されます。これにより、同じものを使用すると効率が向上します。ラムダ式を複数回。
Test#create()がインスタンスのプロパティまたはメソッドを参照する場合、以下の例のようにthis.ToString();を呼び出します。その場合、コンパイラはインスタンスメソッドのロジックを置き換える静的メソッドを作成できないため、GC後にHandleMessageインスタンスを収集できます。
namespace Test
{
class Test
{
public delegate void HandleMessage(string message);
public void handleMessage(string message)
{
}
public HandleMessage create()
{
return (message) => {
//this.ToString();
};
}
static void Main(string[] args)
{
HandleMessage listener1 = new Test().handleMessage;
WeakReference w1 = new WeakReference(listener1);
HandleMessage listener2 = new Test().create();//(message) => { };
WeakReference w2 = new WeakReference(listener2);
Console.WriteLine("w1.Target:\t[" + w1.Target + "]");
Console.WriteLine("w2.Target:\t[" + w2.Target + "]");
listener1 = null;
listener2 = null;
GC.Collect();
Console.WriteLine("after GC");
Console.WriteLine("w1.Target:\t[" + w1.Target + "]");
Console.WriteLine("w2.Target:\t[" + w2.Target + "]");
Console.ReadLine();
}
}
}