C# 闭包对垃圾回收器的奇怪影响
本文关键字:影响 闭包 | 更新日期: 2023-09-27 17:56:12
直接进入代码
class Program
{
private static WeakReference<EventHandler<EventArgs>> _noClosure;
private static WeakReference<EventHandler<EventArgs>> _closure;
static void Main(string[] args)
{
Init();
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
EventHandler<EventArgs> target;
Console.WriteLine(_closure.TryGetTarget(out target));
Console.WriteLine(_noClosure.TryGetTarget(out target));
}
class C { public void Go() { } }
private static void Init()
{
_noClosure = new WeakReference<EventHandler<EventArgs>>((sender, args) =>
{
});
var s = new C();
_closure = new WeakReference<EventHandler<EventArgs>>((sender, args) =>
{
s.Go();
});
}
}
我从这段代码中得到的输出是
False
True
这到底是怎么回事?
附言我在试图弄清楚WeakEventManager
是如何工作的时进入了这个。
编译器
会将_noClosure
委托缓存在静态字段中,并在每次调用Init
时重用它。完全相同的实例每次都可以重复使用。
将其与 _closure
进行比较,后者在每次调用 Init()
时关闭一个新的C()
实例 - 无法缓存。
_noClosure
缓存意味着存在对委托的强引用(字段),因此不能对其进行垃圾回收。
如果在应用程序上运行ildasm
,则可以看到所有这些操作。