Car*_*ven 6 c# delegates weak-references
在我看来,当我WeakReference在对象类的委托方法上使用该类时,对象类被GC收集,但是还有另一个副本驻留在WeakReference?
我觉得用文字解释很难.我举个例子.我有以下对象类调用TestObject:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
现在,在我的主要应用程序,我试图参见方法TestMethod中TestObject通过WeakReference.目的是TestObject在所有硬参考都消失时由GC收集.这是我的主应用程序的样子:
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();
}
Run Code Online (Sandbox Code Playgroud)
这是我运行上面代码时的输出:

这是奇怪的事情.在第一行,obj可以打印,"Hello 1"因为它刚刚初始化并obj持有对该的引用TestObject.全对了.接下来,obj设置为null与obj = nullGC被迫收集.因此,在输出的第二行,obj是truenull.最后在最后一行,由于GC已经收集了obj,我希望它可以抛出一个NullReferenceException或只是在输出上打印.但是,它实际上打印的内容与输出的第一行相同!TestObject此时GC 不应该收集吗?!
这引出了一个问题,如果我将obj设置为null之后,GC TestObject是否先obj收集了该信息.
如果我已经将整个对象传递给了WeakReference,即new WeakReference(obj)代替了代理WeakReference,那么它就会完美地运行.
不幸的是,在我的代码中,我需要传递给WeakReference一个委托.我怎样才能WeakReference正常工作,以便GC只能通过引用委托来收集对象?
我认为问题出在你的测试中 - 而不是在框架中.似乎将局部变量设置为null并不能达到预期效果.如果我们完全跳过局部变量,我们在'after'行得到预期的NullReferenceException:
static void Main(string[] args)
{
var list = new List<WeakReference>();
//var obj = new TestObject("Hello 1");
list.Add(new WeakReference(new TestObject("Hello 1").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();
}
Run Code Online (Sandbox Code Playgroud)