当前位置:  开发笔记 > 编程语言 > 正文

CLR什么时候说对象有终结器?

如何解决《CLR什么时候说对象有终结器?》经验,为你挑选了1个好方法。

我知道在C#中,如果你写~MyClass(),这基本上转化为override System.Object.Finalize().因此,无论您是否编写析构函数,CLR中的每个类型都会有一个Finalize()方法(System.Object至少).

1]那么,这是否意味着,默认情况下,每个对象都有一个终结器?

2] CLR决定一个对象应该通过终结队列的基础是什么?

我问这个,因为,我有一个课,说ManagedResourceHolder实施IDisposable,但没有调用GC.SuppressFinalize(this)它的IDisposable.Dispose()方法.该类没有任何非托管资源,并且不需要该~ManagedResourceHolder()方法,这反过来意味着不需要 GC.SuppressFinalize(this)调用,因为没有终结器.

3]在上述场景的上下文中,在实现IDisposable时是否总是需要提供终结器?(即使在没有非托管资源的类上)

该FxCop的规则CA1816是给我一个违反了这一点,我得到的回应在这里,当我问在MSDN上的CA论坛搞糊涂了.

谢谢.



1> Jon Skeet..:

问题1和2:CLR基本上检查终结器是否被覆盖.如果不是,它会将其视为没有终结器.

在System.Object中使用终结器的好处是编译器知道他们总是可以调用base.Finalize().这可以避免版本控制问题.考虑一个没有的世界System.Object.Finalize():

System.Object(没有Finalize)

Acme.BaseClass(没有Finalize)

MyCompany.DerivedClass(Finalize)

如果没有Finalizeobject中的方法,MyCompany.DerivedClass中的终结器不能调用任何东西.当Acme.BaseClass的第2版带有终结器时会导致问题.除非你重新编译MyCompany.DerivedClass,否则DerivedClass的实例将在不调用BaseClass.Finalize的情况下完成,这显然是一件坏事.

现在考虑 System.Object.Finalize 相同的情况- 编译器在DerivedClass.Finalize中自动插入对base.Finalize的调用,在版本1中只调用System.Object中的no-op实现.当Acme.BaseClass的第2版出来时,对base.Finalizewill 的调用(不重新编译DerivedClass)调用BaseClass.Finalize.

问题3:不,您不需要因为实现IDisposable而拥有终结器.终结器应仅用于非托管资源,其他任何东西都不会被清理 - 即您可以直接引用的资源.例如,假设您有一个具有FileStream成员变量的类.您希望实现,IDisposable以便您可以尽快关闭流,如果调用者记得 - 但如果他们记得调用Dispose(),则流将符合与对象同时进行垃圾回收的条件.信任FileStream具有适当的终结器(或使用终结器等参考其他东西),而不是试图在你自己的终结器中清理它.

从.NET 2.0开始,使用SafeHandle类,您需要自己的终结器应该是非常罕见的.

推荐阅读
wangtao
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有