- 是否应该使用重复的isDisposed变量(因为它已经存在于基类中)?
- 是否也应在子类中实现finalizer?
这两件事在此示例中都已完成 -
然而,这篇MSDN文章中的示例没有这两个内容 - http://msdn.microsoft.com/zh-cn/library/b1yfkh5e.aspx
而这个MSDN中的示例是不完整的 - http://msdn.microsoft.com/zh-cn/library/ms182330.aspx
这两件事在此示例中都已完成 -
然而,这篇MSDN文章中的示例没有这两个内容 - http://msdn.microsoft.com/zh-cn/library/b1yfkh5e.aspx
而这个MSDN中的示例是不完整的 - http://msdn.microsoft.com/zh-cn/library/ms182330.aspx
Dispose
和2)您的Dispose
需要是幂等的(即,无论它被调用一次、两次、5次、100次——如果它被调用多次,它不应该抱怨)。您可以自由地按照自己的方式实现这一点——布尔标志是一种方法,但我经常发现,在我的Dispose
方法中将某些字段设置为null
就足够了,此时就不需要单独的布尔标志了——您可以告诉Dispose
已经被调用,因为您已经将那些字段设置为null
。IDisposable
的指导都极其无用,因为它解决的是需要终结器的情况,但这实际上是非常罕见的情况。这意味着许多人编写的IDisposable
实现比必要的复杂得多。实际上,大多数类调用Stephen Cleary称之为“级别1”的类别,在这个jpierson链接到的文章中,这些类别不需要所有的GC.KeepAlive
、GC.SuppressFinalize
和Dispose(bool)
等杂乱无章的东西。大多数时候,生活实际上要简单得多,正如Cleary针对这些“级别1”类型的建议所示。需要复制
如果子类中没有清理工作,只需调用base.Dispose()
,如果有一些类级别的清理工作,则在调用base.Dispose()
后执行。您需要将这两个类的状态分开,因此每个类都应该有一个IsDisposed
布尔值。这样,您可以随时添加清理代码。
当您确定一个类为IDisposable
时,您只需告诉GC
我正在处理其清理过程,并且您应该SuppressFinilize
这个类,这样GC
会将它从队列中删除。除非您调用GC.SupressFinalize(this)
,否则对于IDisposable
类不会发生特殊事件。因此,如果按照我提到的实现它,就不需要Finilizer
,因为您刚刚告诉GC
不要对其进行终结。
IDisposable
实现特殊的实现。如果我们为每个类实现一个空模式,那么就会浪费更多时间。因此,如果您在派生类中没有特殊的清理,请不要覆盖基类。基类Dispose将自动调用。但是,如果您覆盖了它,请记得调用base.Dispose()
。 - Tomas Van Joseph实现IDisposable的正确方式取决于您的类是否拥有任何非托管资源。实现IDisposable的确切方式仍然是一些开发人员意见不一致的问题,一些人像Stephen Cleary那样对一般的可释放模式持有强烈观点。
IDisposable接口的文档也简要说明了这一点,本文也指出了一些相同的内容,但也在MSDN上进行了介绍。
关于基类是否需要一个重复的布尔字段“isDisposed”。看起来这主要是一个有用的约定,当子类本身可能添加额外的未托管资源需要处理时可以使用。由于Dispose被声明为虚拟方法,在子类实例上调用Dispose总是导致该类的Dispose方法首先被调用,然后调用base.Dispose作为其最后一步,给每个继承层次结构中的级别清理的机会。因此,我可能会总结为,如果您的子类具有超出基类所拥有的其他未托管资源,则最好在其Dispose方法内跟踪其处置的事务性自己的布尔isDisposed字段,但正如Ian在他的答案中提到的那样,还有其他表示已处置状态的方法。
1) 不需要重复
2) 实现终结器将有助于处理未显式处理的项目。但不能保证。这是一个好习惯。
仅在对象保存有关需要清除的内容的信息,并且此信息以某种形式存储于其他需要清理的对象的对象引用之外(例如,作为Int32存储的文件句柄)时,才实现终结器。如果类实现了终结器,则不应保留对未进行清理的任何其他对象的强对象引用。 如果它将持有其他引用,则负责清理的部分应拆分为其自己的具有终结器的对象,并且主对象应保持对其的引用。然后,主对象不应具有终结器。
仅当基类的目的是支持终结器时,派生类才应该具有终结器。如果类的目的并不围绕终结器,那么允许派生类添加终结器没有太大意义,因为几乎可以肯定派生类不应该添加终结器(即使它们需要添加非托管资源,也应将资源放入自己的类中并只保留对其的引用)。