C# IDisposable.Dispose()是否自动调用?
可能重复:C# IDisposable.Dispose()是否自动调用?,c#,.net,idisposable,C#,.net,Idisposable,可能重复: 我有一个类,它有一些非托管资源。我的类实现了IDisposable接口,并在Dispose()方法中释放非托管资源。我必须调用Dispose()方法吗,还是会自动调用它?垃圾收集器会调用它吗?Dispose()不会自动调用。如果有终结器,它将被自动调用。实现IDisposable为类的用户提供了一种提前释放资源的方法,而不是等待垃圾收集器 客户机的首选方法是使用using语句,该语句处理Dispose()的自动调用,即使存在异常 IDisposable的正确实现是: class M
我有一个类,它有一些非托管资源。我的类实现了
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
),托管引用可能无效,因此只能释放非托管资源。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
方法),托管引用可能无效,因此只能释放非托管资源。您必须手动调用此方法,可能(假设“MyClass”实现了“IDisposable”)在类似
using(var myclass = new MyClass())
{
// do something with myclass
}
// now 'myclass'is Disposed
在C#8.0中,您可以编写以下语句:
using var myclass=new MyClass();
“myclass”将在作用域的末尾自动处理
使用语句(与显式调用Dispose()相比)的优点是无论您如何退出此块,都会调用Dispose()
:通过运行到末尾,遇到return
语句或抛出异常。您可能必须手动调用此方法(假设“MyClass”在如下构造中实现“IDisposable”)
using(var myclass = new MyClass())
{
// do something with myclass
}
// now 'myclass'is Disposed
在C#8.0中,您可以编写以下语句:
using var myclass=new MyClass();
“myclass”将在作用域的末尾自动处理
与显式调用Dispose()相比,使用
语句的优点是无论您如何退出此块,都会调用
:通过运行到末尾、遇到return
语句或引发异常。如果您在using
语句中实例化对象,则在代码退出using
块时会为您调用Dispose()
using(var myObject = new MyDisposableObject())
{
blah();
} // Dispose() is called here (or whenever the code exits the block)
如果您没有使用来使用,则由您(调用代码)通过显式调用dispose()来处理对象
此外,如果调用方不调用Dispose(),您(MyObject的实现者)可以添加对终结器的支持。详细信息。如果您在
语句中使用
实例化对象,则当代码退出使用
块时,将为您调用Dispose()
using(var myObject = new MyDisposableObject())
{
blah();
} // Dispose() is called here (or whenever the code exits the block)
如果您没有使用来使用,则由您(调用代码)通过显式调用dispose()来处理对象
此外,如果调用方不调用Dispose(),您(MyObject的实现者)可以添加对终结器的支持。详细信息。要确保正确地释放资源,您需要在析构函数(终结器)中实现
IDisposable
和调用Dispose
为了确保正确地释放资源,您需要在析构函数(终结器)中实现
IDisposable
并调用Dispose
最新添加:当引用超出范围时,不会立即调用该终结器,而是在GC访问它时“一段时间(可能:很长时间)”调用它。因此:不要依赖终结器进行清理听起来像是说如果存在终结器,会自动调用Dispose(即使终结器不调用Dispose方法)。但是显式终结器不会自动调用Dispose方法,除非您显式地将终结器编码为调用Dispose。延迟添加:当引用超出范围时,不会立即调用该终结器,而是“过一段时间(可能:很长时间)”“当GC处理它时。因此:不要依赖终结器进行清理听起来像是说,如果终结器存在,就会自动调用Dispose(即使终结器不调用Dispose方法)。但是显式终结器不会自动调用Dispose,除非您显式地将终结器编码为调用Dispose。为什么
m
前缀?@KyleDelaney几年前我曾给私有成员添加m
前缀…现在我使用
前缀。m
代表成员
。为什么m
代表成员refix?@KyleDelaney几年前我曾给私人成员加前缀,m
,现在我用前缀。m
代表member
。