直接上代码
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
委托(delegate)缓存在静态字段中,并在您每次调用 Init
时重用它。每次都可以重复使用完全相同的实例。
将其与 _closure
进行比较,它会在每次调用 Init()
时关闭 C()
的新实例 - 这不能不被缓存。
_noClosure
的缓存意味着对委托(delegate)有一个强引用(字段),所以它不能被垃圾收集。
如果您在应用程序上运行 ildasm
,您可以看到所有这些操作。
关于c# - C# 闭包对垃圾收集器的奇怪影响,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38267775/