C# 最终确定与处置
为什么有些人使用C# 最终确定与处置,c#,dispose,C#,Dispose,为什么有些人使用Finalize方法而不是Dispose方法 在什么情况下,您会使用Finalize方法而不是Dispose方法,反之亦然?当此对象不再使用时,GC会调用Finalize Dispose只是一个普通的方法,该类的用户可以调用它来释放任何资源 如果用户忘记调用Dispose,并且类已实现Finalize,则GC将确保调用它。当对象被垃圾收集时,将调用finalizer方法,并且您无法保证何时会发生这种情况(您可以强制它,但会影响性能) 另一方面,Dispose方法是由创建类的代码调
Finalize
方法而不是Dispose
方法
在什么情况下,您会使用
Finalize
方法而不是Dispose
方法,反之亦然?当此对象不再使用时,GC会调用Finalize
Dispose只是一个普通的方法,该类的用户可以调用它来释放任何资源
如果用户忘记调用Dispose,并且类已实现Finalize,则GC将确保调用它。当对象被垃圾收集时,将调用finalizer方法,并且您无法保证何时会发生这种情况(您可以强制它,但会影响性能) 另一方面,
Dispose
方法是由创建类的代码调用的,这样您就可以在对对象执行代码时清理并释放您获得的任何资源(非托管数据、数据库连接、文件句柄等)
标准做法是实现
IDisposable
和Dispose
,以便您可以在状态中使用对象。例如使用(var foo=new MyObject()){}
。在终结器中,您调用Dispose
,以防调用代码忘记处置您。Finalize是backstop方法,垃圾收集器在回收对象时调用。Dispose是“确定性清理”方法,由应用程序调用,以在不再需要有价值的本机资源(窗口句柄、数据库连接等)时释放它们,而不是将它们无限期地保留,直到GC开始处理对象
作为对象的用户,始终使用Dispose。最后定稿是为总承包商准备的
作为类的实现者,如果您持有应该被处置的托管资源,那么您将实现Dispose。如果您持有本机资源,则可以实现Dispose和Finalize,并调用释放本机资源的公共方法。这些习惯用法通常通过私有Dispose(bool disposing)方法组合在一起,该方法使用true处理调用,使用false完成调用。此方法总是释放本机资源,然后检查disposing参数,如果该参数为true,则它将处理托管资源并调用GC.SuppressFinalize。99%的时间,您不必担心这两种情况。:)但是,如果对象包含对非托管资源(例如窗口句柄、文件句柄)的引用,则需要为托管对象提供释放这些资源的方法。Finalize为释放资源提供隐式控制。它由垃圾收集器调用。Dispose是一种对资源释放进行显式控制的方法,可以直接调用
关于的主题还有很多要学习的,但这只是一个开始。其他人已经讨论了Dispose
和Finalize
之间的区别(顺便说一句,Finalize
方法在语言规范中仍然称为析构函数),因此,我只想添加一点关于Finalize
方法派上用场的场景
有些类型以一种方式封装了一次性资源,在一次操作中就可以轻松地使用和处置这些资源。通常的用法是:打开、读或写、关闭(Dispose)。它非常适合使用
构造的
其他的则有点困难<代码>WaitEventHandles
对于实例来说并不是这样使用的,因为它们用于从一个线程向另一个线程发送信号。接下来的问题是,谁应该调用Dispose
?作为一种保护措施,这些类型实现了一个Finalize
方法,该方法确保在应用程序不再引用实例时释放资源 完成
- 终结器应始终受到
,而不是保护
或公共
,以便无法直接从应用程序的代码调用该方法,同时,它可以调用私有
方法基。终结
- 终结器应仅释放非托管资源
- 该框架不保证终结器将在任何给定实例上执行
- 决不要在终结器中分配内存或从终结器中调用虚拟方法
- 避免在终结器中同步和引发未处理的异常
- 终结器的执行顺序是不确定的,换句话说,您不能依赖终结器中仍然可用的另一个对象
- 不要在值类型上定义终结器
- 不要创建空的析构函数。换句话说,除非您的类需要清理非托管资源,否则您永远不应该显式定义析构函数,如果您确实定义了一个析构函数,它应该做一些工作。如果以后不再需要清理析构函数中的非托管资源,请将其全部删除
- 在每个具有终结器的类型上实现
IDisposable
- 确保在调用
方法后对象变得不可用。换句话说,避免在对对象调用Dispose
方法后使用该对象Dispose
- 处理完所有
类型后,对它们调用IDisposable
Dispose
- 允许多次调用
,而不会引发错误Dispose
- 使用
方法从GC.SuppressFinalize
方法中抑制以后对终结器的调用Dispose
- 避免创建一次性值类型
- 避免从
方法中引发异常Dispose
- Microsoft建议您在使用非托管资源时同时实现
和Dispose
。Finalize
完成
using System; class DisposableClass : IDisposable { // A name to keep track of the object. public string Name = ""; // Free managed and unmanaged resources. public void Dispose() { FreeResources(true); // We don't need the destructor because // our resources are already freed. GC.SuppressFinalize(this); } // Destructor to clean up unmanaged resources // but not managed resources. ~DisposableClass() { FreeResources(false); } // Keep track if whether resources are already freed. private bool ResourcesAreFreed = false; // Free resources. private void FreeResources(bool freeManagedResources) { Console.WriteLine(Name + ": FreeResources"); if (!ResourcesAreFreed) { // Dispose of managed resources if appropriate. if (freeManagedResources) { // Dispose of managed resources here. Console.WriteLine(Name + ": Dispose of managed resources"); } // Dispose of unmanaged resources here. Console.WriteLine(Name + ": Dispose of unmanaged resources"); // Remember that we have disposed of resources. ResourcesAreFreed = true; } } }
public abstract class DisposableType: IDisposable { bool disposed = false; ~DisposableType() { if (!disposed) { disposed = true; Dispose(false); } } public void Dispose() { if (!disposed) { disposed = true; Dispose(true); GC.SuppressFinalize(this); } } public void Close() { Dispose(); } protected virtual void Dispose(bool disposing) { if (disposing) { // managed objects } // unmanaged objects and resources } }
class ClassWithDisposeAndFinalize : IDisposable { // Used to determine if Dispose() has already been called, so that the finalizer // knows if it needs to clean up unmanaged resources. private bool disposed = false; public void Dispose() { // Call our shared helper method. // Specifying "true" signifies that the object user triggered the cleanup. CleanUp(true); // Now suppress finalization to make sure that the Finalize method // doesn't attempt to clean up unmanaged resources. GC.SuppressFinalize(this); } private void CleanUp(bool disposing) { // Be sure we have not already been disposed! if (!this.disposed) { // If disposing equals true i.e. if disposed explicitly, dispose all // managed resources. if (disposing) { // Dispose managed resources. } // Clean up unmanaged resources here. } disposed = true; } // the below is called the destructor or Finalizer ~ClassWithDisposeAndFinalize() { // Call our shared helper method. // Specifying "false" signifies that the GC triggered the cleanup. CleanUp(false); }