c# - C# 闭包对垃圾收集器的奇怪影响

标签 c# .net garbage-collection weak-references

直接上代码

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/

相关文章:

c# - 在 C# 中使用 XSLT 将 XML 转换为 HTML 的最简单方法?

c# - 绕过聚合根

c# - 如何在 lucene 搜索中添加特殊字符? C#

.net - 是否可以使用 ICriteria 从 NHibernate 查询中获取惰性 IEnumerable?

c# - 来自 user32.dll 的 FindWindowEx 使用 dllimport 返回零句柄和 127 错误代码

c# - 使用泛型的接口(interface) "Cannot implicitly convert type"

c# - TypeLoadException的解决方法

garbage-collection - 垃圾收集器的内存屏障实现

c# 多线程内存使用 - 应用程序变慢和 CPU 使用率下降

java - 在 Java 中使用弱引用的成本