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();
}
}
}
Почему w2.Target не равен NULL после GC?
w1.Target: [Test.Test+HandleMessage]
w2.Target: [Test.Test+HandleMessage]
after GC
w1.Target: []
w2.Target: [Test.Test+HandleMessage]
EDIT
Спасибо за все ответы, Брайан Расмуссен и Джон Скит, ваши ответы верны. Теперь я полностью понимаю, что происходит, поэтому я написал еще один пример, чтобы все было более наглядно.
Следующий пример показывает, что:
Если Test # create () не ссылается на какие-либо свойства или методы экземпляра, то компилятор создаст "приватное статическое HandleMessage CS $ <> 9__CachedAnonymousMethodDelegate1", как сказал Джон Скит. Это делает его более эффективным, когда вы использовать одно и то же лямбда-выражение несколько раз.
Если Test # create () ссылается на свойства или методы экземпляра, как в примере ниже, вызывая this.ToString (); тогда компилятор не может создать статический метод для замены логики метода intstance, поэтому после 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();
}
}
}