c# - 如何处理实现 IDisposable 的类中的委托(delegate)/事件引用

标签 c# .net events delegates idisposable

我一直在阅读有关内存管理的文章,并在一个项目中遇到过这样的情况,无论是本书还是谷歌都没有给出确切的答案。我已经知道委托(delegate)是管理对象,事件是委托(delegate)实例。话虽如此,一旦应用程序结束,委托(delegate)实例将从内存中删除。

我想不通的是如何确保外部代码在我的类被处置时(明确地或由 GC)释放所有事件引用。例如,类 A 公开一个事件,类 B 使用它。类 B 在类 A 上调用 Dispose 而不释放对委托(delegate)的引用。当然,我们不能从 Dispose 方法本身抛出错误。

下面是一个带有委托(delegate)的类和另一个使用委托(delegate)的类。

public class ClassB
{
    private ClassA A { get; set; }

    public ClassB()
    {
        this.A = new ClassA();
        this.A.OnProcessed += new ClassA.DelegateProcessed(this.ClassA_Processed);
    }

    public void Process()
    {
        this.A.Process();
    }

    public void ClassA_Processed (ClassA sender, EventArgs e)
    {
        // Do something.

        // Code written by another developer does not free up events before calling Dispose.

        this.A.Dispose();
        this.A = null;
    }
}

public class ClassA: IDisposable
{
    public delegate void DelegateProcessed (A sender, EventArgs e);
    public event DelegateProcessed OnProcessed = null;

    ~ClassA() { this.Dispose(false); }

    public void Dispose ()
    {
        this.Dispose(true);
        System.GC.SuppressFinalize(this);
    }

    private void Dispose (bool disposing)
    {
        if (!this.Disposed)
        {
            if (disposing)
            {
                // Dispose managed resources here.
                // Is it possible / advisable to dispose of delegates / events here?
                // Will this adversely affect the consumer class?
                this.OnProcessed -= new ClassA.DelegateProcessed(this.ClassA_Processed);
            }
        }
        this.Disposed = true;
    }

    public void Process () { this.OnProcessed(this, new EventArgs()); }

    public void ClassA_Processed (ClassA sender, EventArgs e) { }
}

关键是要确保无论开发人员对 ClassB 做什么,ClassA 都符合垃圾回收的条件。重点是尽量减少 ClassA 在内存中花费的时间,即使消费者不小心也是如此。

更新:从答案中可以清楚地看出,事件不必明确从 ClassA 中删除。至于主要问题,弱引用似乎是解决问题的方法,如下所述。目标是最小化 ClassA 在内存中的停留时间。如果我忽略了任何事情,请告诉我。

最佳答案

IDisposable 用于确定性地释放非托管资源。

无需删除事件处理程序。例如,如果您查看 Windows 窗体 FormUserControl 类,或者 ASP.NET PageUserControl 类,所有这些都是 IDisposable,您会看到事件的广泛使用,并且在处置期间没有特殊处理。

关于c# - 如何处理实现 IDisposable 的类中的委托(delegate)/事件引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12566584/

相关文章:

c# - 从另一个集合更新 ObservableCollection

c# - Azure WebJob 的 BlobInput 和 BlobOutput 类在哪里?

java - Gradle - 如果项目仍然具有 SNAPSHOT 依赖项,则抛出异常

.net - 用于 Windows Server 事务/错误处理的服务总线 1.0

php - Symfony DI 容器中的配置证明

c# - MVVM 最佳实践 : communication between view models

c# - Linq 表达式从最后一个函数获取谓词项

events - Magento 添加新产品事件观察者

javascript - 有没有办法判断某个事件是否已在之前的冒泡阶段中得到处理?

c# - 如何将 "int"分配给对象?