我知道实施配置模式的一般准则警告不要实现虚拟Dispose().但是,大多数情况下,我们只使用类中的托管资源,因此完整的部署模式似乎有点过分 - 即我们不需要终结器.在这种情况下,Dispose()在基类中使用虚拟是否可以?
考虑这个简单的例子:
abstract class Base : IDisposable
{
private bool disposed = false;
public SecureString Password { get; set; } // SecureString implements IDisposable.
public virtual void Dispose()
{
if (disposed)
return;
if (Password != null)
Password.Dispose();
disposed = true;
}
}
class Sub : Base
{
private bool disposed = false;
public NetworkStream NStream { get; set; } // NetworkStream implements IDisposable.
public override void Dispose()
{
if (disposed)
return;
if (NStream != null)
NStream.Dispose();
disposed = true;
base.Dispose();
}
}
Run Code Online (Sandbox Code Playgroud)
我觉得这比完整的配置模式更具可读性.据我所知,如果我们将非托管资源引入Base类中,这个示例将会成为问题.但是假设这不会发生.以上示例是有效/安全/健壮的,还是会造成任何问题?即使没有使用非托管资源,我是否应该坚持标准的完整配置模式?或者上述方法在这种情况下确实完全正常 - 根据我的经验,这比处理非托管资源更常见?
IDisposable在我没有处理非托管资源的情况下,我已经放弃了完整的模式.
如果你能确保派生类不会引入非托管资源,我看不出你为什么不能放弃模式和Dispose虚拟化的原因!
(这里存在一个问题,因为你不能强制执行这个.你无法控制派生类将添加哪些字段,所以虚拟没有绝对的安全性Dispose.但是即使你使用了完整的模式,派生的也是如此. class可能会出错,因此总有一些信任涉及子类型遵守某些规则.)
首先,在我们只处理托管对象的情况下,使用终结器是没有意义的:如果Dispose 从终结器调用(Dispose(disposing: false)根据完整模式),我们可能无法安全地访问/取消引用其他引用类型的托管对象,因为它们可能已经不见了 只能安全地访问从最终确定的对象可到达的值类型对象.
如果终结器没有意义,那么拥有disposing标志也是没有意义的,该标志用于区分是否Dispose显式调用或是否由终结器调用.
GC.SuppressFinalize 如果没有终结器,也没有必要这样做.
我甚至不确定是否仍然必须(参见下面的 @ usr 评论.)Dispose 在仅托管方案中抛出任何异常.AFAIK这个规则主要用于保护终结器线程.
正如您所看到的,一旦终结器出现,就不再需要大部分经典的Disposable模式.
| 归档时间: |
|
| 查看次数: |
236 次 |
| 最近记录: |