对象不会被垃圾收集

MTR*_*MTR 13 c# events garbage-collection destructor

我认为这是一个C#初学者问题,但我似乎无法找到正确的解决方案.

我有一个ClassOne对象,它定义了一个事件.我创建了一个ClassTwo对象,它被认为是一个黑盒子,这意味着我不知道它是否会注册到任何事件.ClassTwo构造函数注册到ClassOne的事件.当ClassTwo对象超出范围时,问题就出现了.垃圾收集器永远不会删除此对象,因为它从未取消注册该事件.

所以我有两个问题:

  1. 当ClassTwo对象超出范围时,有没有办法知道?对于一个旧的C++程序员来说,这将是在析构函数中,但是使用C#这不起作用.

  2. 有没有一个调试工具可以帮助我找到这样的对象?

以下是重现问题的示例代码:

    public partial class MainWindow : Window
{
    static public ClassOne classOne = new ClassOne();
    public MainWindow()
    {
        InitializeComponent();
        ClassTwo classtwo = new ClassTwo();
    }

    private void buttonTest_Click(object sender, RoutedEventArgs e)
    {
        GC.Collect();
    }
}
public class ClassOne
{
    public ClassOne()
    {
        Trace.WriteLine(this + " constructor");
    }

    ~ClassOne()
    {
        Trace.WriteLine(this + " destructor");
    }

    public delegate void UpdateFunc(object sender, EventArgs args);
    public event UpdateFunc OnUpdate;

}
public class ClassTwo
{
    public ClassTwo()
    {
        Trace.WriteLine(this + " constructor");
        MainWindow.classOne.OnUpdate += new ClassOne.UpdateFunc(classOne_OnUpdate);
    }

    void classOne_OnUpdate(object sender, EventArgs args)
    {
        throw new NotImplementedException();
    }

    ~ClassTwo()
    {
        Trace.WriteLine(this + " destructor");
    }
}
Run Code Online (Sandbox Code Playgroud)

Dan*_*rth 6

我会IDisposable在这样的对象上实现并从Dispose方法中的事件中取消注册.你会像这样使用你的对象:

using(var two = new ClassTwo(classOne))
{
    // Do something with two
}
// object can now be garbage collected.
Run Code Online (Sandbox Code Playgroud)

如果来电者没有打电话Dispose,那你就不走运了.


Meh*_*dad 5

  1. 除非它实现并且调用者通过正确调用进行协作.(当然,为什么呼叫者不合作?)IDisposable Dispose

  2. 不是我的.:(我认为你最好的选择是实施IDisposable和取消注册Dispose.