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();
}
}
}
Pourquoi w2.Target n'est pas nul après GC?Lambda Expression car la cible de référence faible ne peut pas être GC?
w1.Target: [Test.Test+HandleMessage] w2.Target: [Test.Test+HandleMessage] after GC w1.Target: [] w2.Target: [Test.Test+HandleMessage]
EDIT
Merci pour toutes les réponses, Brian Rasmussen et Jon Skeet vos réponses sont correctes. Maintenant, je comprends parfaitement ce qui se passe, alors j'ai écrit un autre exemple pour rendre tout plus clair.
L'exemple suivant montre que:
Si # test create() ne fait pas référence à des propriétés d'instance ou des méthodes, puis "HandleMessage private static CS < $> 9__CachedAnonymousMethodDelegate1" sera créé par le compilateur, comme ce que Jon Skeet a dit - Cela le rend plus efficace lorsque vous utilisez la même expression lambda plusieurs fois.
Si le test # create() fait référence à des propriétés ou des méthodes d'instance, comme dans l'exemple ci-dessous appelant this.ToString(); alors le compilateur ne peut pas créer une méthode statique pour remplacer la logique de la méthode intstance, donc après GC, l'instance HandleMessage peut être collectée.
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();
}
}
}
Il n'y a pas de finaliseur, donc le code de l'OP suffira dans ce cas. –