是否自动调用IDisposable.Dispose()
本文关键字:Dispose IDisposable 调用 是否 | 更新日期: 2023-09-27 18:04:36
可能重复:
垃圾回收器会为我调用IDisposable.Dispose吗?
我有一个类,它有一些非托管资源。我的类实现了IDisposable
接口,并释放了Dispose()
方法中的非托管资源。我必须调用Dispose()
方法吗?还是会以某种方式自动调用它?垃圾回收员会叫它吗?
Dispose()
将不会被自动调用。如果存在终结器,它将被自动调用。实现IDisposable
为类的用户提供了一种提前释放资源的方法,而不是等待垃圾收集器。
对于客户端来说,最好的方法是使用using
语句,即使存在异常,该语句也会处理Dispose()
的自动调用。
IDisposable
的正确实现是:
class MyClass : IDisposable
{
private bool disposed = false;
void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if(!disposed)
{
if(disposing)
{
// Manual release of managed resources.
}
// Release unmanaged resources.
disposed = true;
}
}
~MyClass() { Dispose(false); }
}
如果类的用户调用Dispose()
,则直接进行清理。如果对象被垃圾收集器捕获,它将调用Dispose(false)
进行清理。请注意,从终结器(~MyClass
方法(调用时,托管引用可能无效,因此只能释放非托管资源。
如果您在using
语句中实例化对象,当代码退出using
块时,将为您调用Dispose((
using(var myObject = new MyDisposableObject())
{
blah();
} // Dispose() is called here (or whenever the code exits the block)
如果不使用using
,则由您(调用代码(通过显式调用dispose((来处理对象。
此外,您(MyObject的实现者(可以添加对终结器的支持,以防调用者没有调用Dispose((。点击此处了解更多信息。
您将必须手动调用此方法,可能(假设"MyClass"实现了"IDisposable"(在类似的构造中
using(var myclass = new MyClass())
{
// do something with myclass
}
// now 'myclass'is Disposed
在C#8.0中,您可以编写以下语句:
using var myclass=new MyClass();
并且"myclass"将在作用域的末尾自动处理。
using
语句的优点(与显式调用Dispose((相比(是,无论您如何退出此块,都会调用Dispose()
:通过运行到末尾、遇到return
语句或引发异常。
要确保资源得到正确部署,需要在析构函数(终结器(中实现IDisposable
并调用Dispose
。
class Foo : IDisposable
{
private bool m_disposed = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~Foo()
{
Dispose(false);
}
protected void Dispose(bool disposing)
{
if (!m_disposed)
{
if (disposing)
{
//release managed resources
}
//release unmanaged resources
m_disposed = true;
}
}
}