C# 终结器和IDisposable
根据文档(MSDN:),很明显在实现终结器时应该使用IDisposable模式 但是,如果实现IDisposable(以便提供处理对象的确定方法),并且没有任何非托管资源需要清理,那么是否需要实现终结器 在我看来,如果类只有托管资源,而您不调用Dispose,那么托管资源将被GC自动清理,因此无需实现终结器。我错了吗C# 终结器和IDisposable,c#,dispose,idisposable,finalizer,garbage-collection,C#,Dispose,Idisposable,Finalizer,Garbage Collection,根据文档(MSDN:),很明显在实现终结器时应该使用IDisposable模式 但是,如果实现IDisposable(以便提供处理对象的确定方法),并且没有任何非托管资源需要清理,那么是否需要实现终结器 在我看来,如果类只有托管资源,而您不调用Dispose,那么托管资源将被GC自动清理,因此无需实现终结器。我错了吗 另外,如果我正在使用Dispose方法清理事件处理程序呢。由于Dispose不会自动被GC调用,我是否应该实现一个终结器,以确保EventHandler不被激活?除非您有非托管资源
另外,如果我正在使用Dispose方法清理事件处理程序呢。由于Dispose不会自动被GC调用,我是否应该实现一个终结器,以确保EventHandler不被激活?除非您有非托管资源,否则不应该添加终结器 拥有托管的可支配资源而不是非托管资源的类应该实现完整的
Dispose
模式,但不具有终结器
如果类不是
密封的
,它应该在其Dispose()
方法中调用GC.SuppressFinalize(this)
,以防继承的类添加终结器。如果您只有托管资源,那么您根本不需要实现IDisposable。IDisposable用于清理GC域之外的内容,如本机句柄、数据库连接等
如果您的控件包含实现IDisposable的控件,并且它们必须释放本机资源,那么您仍然需要实现IDisposable模式,并给您的子控件一个释放的机会
在终结器中调用Dispose()的原因是作为最后手段,如果对象未正确处置,GC将做最后的努力。是的,如果您只有托管资源,则在垃圾收集发生时,GC将清理这些资源(并且没有任何指向它们的活动引用) 但是在这种情况下,为什么需要在您的类型上实现IDisposable?我的意思是,你似乎认为,在你的情况下,不处理你的对象不是一个大问题,那么为什么会有人处理它们? 您还应该注意到,在使用终结器时,垃圾收集会导致性能下降:任何带有终结器的对象都会逃逸第一次GC传递,如果这些对象的生命周期很短,这将大大降低GC效率
在应该清理对象的第一次垃圾收集期间,为了执行终结器,它不会清理。然后,GC会认为该对象是长寿命的,即使它已经被清除。不,如果您有一个实现IDisposable的类(即如果您正确实现了该模式,并且您只有可处置的托管资源),则无需实现终结器
(如果这样做,它实际上会影响对象的生存期,因为带有终结器的对象会被添加到GC中的终结队列中,并且可能比它们需要的时间更长—如果对象很大,这可能是一个问题。)我从未需要实现终结器。如您所知,它使对象有机会在GC之前执行它需要的任何操作。应释放dispose方法中的所有资源
因为直接处理非托管资源的情况相对较少,所以很有可能您永远不必编写定稿器(我想我曾经在实际代码中这样做过一次)。因为明智的人在处理非托管资源的类中不会做太多其他事情,所以整个Dispose(bool)工作也没有必要。如果继承的类也会添加非托管资源呢?@Henk:这就是为什么它会添加终结器。(和覆盖
Dispose(bool)
)@Henk:Huh?你在说什么SuppressFinalize
由非虚拟的Dispose()
方法调用,在任何情况下都应该调用。如果派生类添加了非托管资源,它应该在Dispose(bool)
中清理它,并添加一个调用Dispose(false)
的终结器。如果调用了普通的Dispose
方法,则非托管资源将被清除,因此终结器应该被抑制。我认为您应该在可终结类(无论是否密封)中的Dispose()中调用GC.SuppressFinalize(this)。也就是说,我还是要将其密封起来,而不使用Dispose(bool)反模式。@Jon:如果该类是密封的,并且没有终结器,那么调用SuppressFinalize
就没有意义了。非托管资源必须由终结器清理(和Dispose;请参见模式)除了SafeHandle之外,任何新编写的类持有非托管资源的原因是什么?显然,早于SafeHandle的类必须这样做,但新编写的类是否有这样做的空间?@Rajah:我们的答案并不矛盾。然而,我是对的;见和@Rajah:a