我有一个A类,该类实现了Disposable模式,以便释放非托管资源,例如取消订阅事件。类B使用类A,但不将其包装在using {..}块中,也不显式调用A.Dispose(true),因此A.dispose是通过标准Dispose(false)调用在A的终结器中调用的。但是随后通过将bool参数设置为false,将不会清除非托管资源,即不会取消订阅事件。终结器不应该调用Dispose(true)还是B类应该在某个时刻(例如在其自身的终结器中)显式调用A.Dispose(true)?
this.ngZone.run(() => {
this.store.dispatch(new ResetSettingsProgressValue(setting));
this.store.dispatch(new LoadSettingsProgressValue(setting));
});
答案 0 :(得分:2)
实施Disposable模式,以释放非托管资源,例如取消订阅事件。
退订事件不是需要清除的非托管资源。
B类使用A类,但不将其包装在using {..}块中,也不显式调用A.Dispose(true)
您应该将其视为程序中的错误。实施IDisposable
的全部目的是因为该对象需要由所有者来明确清理。
但是通过将bool参数设置为false,将不会清除非托管资源,
但是这些不是非托管资源,这就是为什么它们不会在finally块中清除的原因。
终结器不应该调用Dispose(true)还是B类应该在某个时刻(例如在其自身的终结器中)显式调用A.Dispose(true)?
不。您不应该在终结器中与托管对象进行交互。这样做是不安全的。由于您没有非托管资源可在终结器中清除,因此您甚至不应该拥有终结器。
答案 1 :(得分:0)
dispose方法必须仅使用dispose参数来决定是否释放托管资源。非托管资源必须始终被释放。
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
// Free managed resources
}
// always free unmanaged resources
_disposed = true;
}
}
如果Dispose调用是通过垃圾收集器发生的(=通过对Finalizer的调用),并且Dispose为false,则不需要释放托管资源。垃圾收集器还将调用那些托管对象的终结器(甚至可能更早)。
在第二个重载中,dispose参数是一个布尔值, 指示方法调用是否来自Dispose方法(其 值是true)或终结器(值是false)。
该方法的主体由两个代码块组成:
释放非托管资源的块。不管dispose参数的值如何,该块都会执行。
一个释放托管资源的条件块。如果dispose的值为true,则执行此块。托管资源 免费包括:
实现IDisposable的托管对象。条件块可用于调用其Dispose实现。如果您使用过 安全包装非托管资源的句柄,您应该调用 SafeHandle.Dispose(Boolean)实现在这里。
消耗大量内存或消耗稀缺资源的托管对象。在“处置”中显式释放这些对象 方法释放它们的速度比回收它们的速度快 由垃圾收集器不确定地确定。
如果方法调用来自终结器(即,如果处置是 false),仅执行释放非托管资源的代码。因为 垃圾收集器销毁托管对象的顺序 在完成期间未定义,使用以下方法调用此Dispose重载 值为false阻止终结器尝试释放托管对象 可能已经被回收的资源。