Es scheint mir, dass, wenn ich die WeakReference
Klasse für eine Delegate-Methode einer Objektklasse verwenden, die Objektklasse vom GC gesammelt wird, aber es gibt noch eine weitere Kopie davon in der WeakReference
?GC wird nicht erfasst, wenn WeakReference auf einen Delegaten verweist?
Ich finde es schwierig, in Worten zu erklären. Ich werde ein Beispiel geben. Ich habe folgende Objektklasse TestObject
genannt:
class TestObject
{
public string message = "";
private delegate string deleg();
public TestObject(string msg)
{
message = msg;
}
public Delegate GetMethod()
{
deleg tmp = this.TestMethod;
return tmp;
}
public string TestMethod()
{
return message;
}
}
Nun, in meiner Hauptanwendung, ich versuche TestMethod
über ein WeakReference
in TestObject
auf das Verfahren zu beziehen. Die Absicht ist, dass die TestObject
durch GC gesammelt werden kann, wenn alle harten Referenzen weg sind. Dies ist, wie meine Hauptanwendung wie folgt aussieht:
static void Main(string[] args)
{
var list = new List<WeakReference>();
var obj = new TestObject("Hello 1");
list.Add(new WeakReference(obj.GetMethod()));
Console.WriteLine("Initial obj: " + ((Delegate)list[0].Target).DynamicInvoke()); //Works fine
obj = null; //Now, obj is set to null, the TestObject("Hello 1") can be collected by GC
GC.Collect(); //Force GC
Console.WriteLine("Is obj null: " + ((obj) == null ? "True" : "False"));
Console.WriteLine("After GC collection: " + ((Delegate)list[0].Target).DynamicInvoke());
Console.ReadKey();
}
Dies ist der Ausgang, wenn ich den obigen Code auszuführen:
Hier ist die seltsame Sache. In der ersten Zeile, obj
könnte drucken "Hello 1"
, weil es gerade initialisiert wurde und obj
hielt einen Verweis auf die TestObject
. Alles richtig. Als nächstes wurde obj
auf null
mit obj = null
gesetzt und GC wurde gezwungen zu sammeln. Also, in der zweiten Zeile des Ausgangs, obj
ist true
null zu sein. Schließlich auf der letzten Zeile, seit der GC hat die obj
weg gesammelt, ich erwarte, dass es entweder eine NullReferenceException
werfen oder nur nichts auf dem Ausgang drucken. Es hat jedoch tatsächlich dasselbe gedruckt wie in der ersten Zeile des Ausgangs! Sollte die TestObject
zu diesem Zeitpunkt noch nicht vom GC abgeholt werden ?!
Dies wirft die Frage auf, ob der TestObject
, der zuerst in obj
gehalten wurde, später vom GC gesammelt wurde oder nicht, nachdem ich obj auf null gesetzt habe.
Wenn ich das ganze Objekt in WeakReference
, dh new WeakReference(obj)
, statt eines Delegierten in die WeakReference
übergeben hatte, hätte es perfekt funktioniert.
Leider in meinem Code muss ich in die WeakReference
einen Delegaten übergeben. Wie kann ich die WeakReference
korrekt funktionieren lassen, damit der GC das Objekt sammeln kann, indem nur auf einen Delegaten verwiesen wird?