Bub*_*rap 10 c# weak-references
请考虑以下代码:
class Program
{
static void Main(string[] args)
{
A a = new A();
CreateB(a);
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("And here's:" + a);
GC.KeepAlive(a);
}
private static void CreateB(A a)
{
B b = new B(a);
}
}
class A
{ }
class B
{
private WeakReference a;
public B(A a)
{
this.a = new WeakReference(a);
}
~B()
{
Console.WriteLine("a.IsAlive: " + a.IsAlive);
Console.WriteLine("a.Target: " + a.Target);
}
}
Run Code Online (Sandbox Code Playgroud)
使用以下输出:
a.IsAlive: False
a.Target:
And here's:ConsoleApp.A
Run Code Online (Sandbox Code Playgroud)
为什么它是假的而且是空的?尚未收到A.
编辑:哦,你们没有信心.
我添加了以下几行:
Console.WriteLine("And here's:" + a);
GC.KeepAlive(a);
Run Code Online (Sandbox Code Playgroud)
查看更新的输出.
更新问题的更新答案。
有了新问题,我们将执行以下步骤。
(如果 B 在第 4 点完成,则有可能在第 5 点之前被收集,因为 B 等待最终确定会使 B 和 Ba 都无法被收集,而 Ba 等待最终确定不会影响 B 的收集)。
所发生的情况是,4 和 5 之间的顺序是 Ba 被最终确定,然后 B 被最终确定。由于 WeakReference 持有的对象引用不是普通引用,因此它需要自己的清理代码来释放其 GCHandle。显然它不能依赖于正常的 GC 收集行为,因为其引用的全部要点是它们不遵循正常的 GC 收集行为。
现在 B 的终结器已运行,但由于 Ba 的终结器的行为是释放其引用,因此它为 IsAlive 返回 false(或者在 1.1 之前的 .NET 中,如果我没记错版本,则会引发错误)。