我在类中实现finalize和dispose,在父类中实现idisposable并重写子类中的dispose(bool)重载。我不确定
是否使用重复的isDisposed变量(因为它已经存在于基类中)?
是否也在子类中实现终结器?
这两件事都是在这里给出的例子中完成的-
http://guides.brucejmack.biz/CodeRules/FxCop/Docs/Rules/Usage/DisposeMethodsShouldCallBaseClassDispose.html
然而,本文中的示例没有这两个-
http://msdn.microsoft.com/en-us/library/b1yfkh5e.aspx
然而,msdn中的这个示例并不完整-
http://msdn.microsoft.com/en-us/library/ms182330.aspx
最佳答案
很少有定稿器有用。您链接到的文档并不是完全有用的—它提供了以下相当循环的建议:
仅在对象上实现finalize
需要定稿的
这是一个很好的乞求问题的例子,但并不是很有帮助。
在实践中,绝大多数情况下你都不需要定稿器。(net开发人员必须经历的一个学习曲线是发现,在大多数他们认为需要终结器的地方,他们不需要终结器。)您将此标记为(除其他外)wpf问题,我认为在ui对象上放置终结器几乎总是一个错误。(因此,即使您遇到了一种不寻常的情况,结果证明需要终结器,但该工作不属于任何与wpf相关的代码附近。)
对于大多数终结器看起来可能有用的场景,结果却不是这样,因为当终结器运行时,它已经太晚了,无法执行任何有用的操作。
例如,尝试对对象引用的任何对象执行任何操作通常是一个坏主意,因为在终结器运行时,这些对象可能已经完成。(.NET无法保证终结器的运行顺序,因此您根本无法知道是否有要终结的引用的对象。)对已运行终结器的对象调用方法是不明智的。
如果你有某种方式知道某个对象肯定还没有最终确定,那么使用它是安全的,但这是一个非常不寻常的情况。(…除非所讨论的对象没有终结器,并且没有使用可终结的资源本身。但在这种情况下,当你自己的对象离开时,你可能不需要对它做任何事情。)
终结器似乎有用的主要情况是互操作:例如,假设您使用p/invoke调用一些非托管api,并且该api返回一个句柄。也许你需要调用其他的api来关闭这个句柄。因为这都是非托管的东西,.net gc不知道这些句柄是什么,您的工作是确保它们被清理干净,此时终结器是合理的……除了在实践中,几乎总是最好对该场景使用SafeHandle
。
在实践中,我发现自己使用终结器的唯一地方是a)设计用于调查gc做什么的实验,b)设计用于发现系统中如何使用特定对象的诊断代码。这两种代码都不应该最终投入生产。
所以,你是否需要“在儿童班也实现终结器”的答案是:如果你需要问,那么答案是不。
至于是否复制国旗…其他的答案在这里提供了矛盾的建议。要点是1)你需要调用基Dispose
和2)你的Dispose
需要是等幂的。(也就是说,调用一次、两次、5次、100次都没关系——如果调用不止一次就不应该抱怨了。)您可以随心所欲地实现这一点——布尔标志是一种方法,但我经常发现,在我的null
方法中,将某些字段设置为Dispose
就足够了,在这一点上,不需要单独的布尔标志-您可以知道已经调用了Dispose
,因为您已经将这些字段设置为null
。
很多关于IDisposable
的指导都是毫无帮助的,因为它解决了需要定稿器的情况,但实际上这是一个非常不寻常的情况。这意味着许多人编写的IDisposable
实现远比必要的复杂。在实践中,大多数类在the article that jpierson linked to中将stephen cleary称为“level 1”。对于这些,您不需要所有的GC.KeepAlive
、GC.SuppressFinalize
和Dispose(bool)
东西,这些东西会使大多数示例变得杂乱无章。事实上,生活在大多数时候都要简单得多,正如cleary对这些“1级”类型的建议所显示的那样。
关于c# - 实现Finalize和Dispose的正确方法(当父类实现IDisposable时),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4439050/