基本上我有一些如下所示的函数:
class MyClass
{
void foo()
{
using (SomeHelper helper = CreateHelper())
{
// Do some stuff with the helper
}
}
void bar()
{
using (SomeHelper helper = CreateHelper())
{
// Do some stuff with the helper
}
}
}
假设我可以在每个函数中使用相同的资源而不是不同的资源[实例],那么在清理等方面这样做可以吗?:
class MyClass
{
SomeHelper helper = CreateHelper();
// ...foo and bar that now just use the class helper....
~MyClass()
{
helper.Dispose();
}
}
不,不要添加析构函数(终结器)。
您可以重用资源,但您的类必须实现IDisposable
。
sealed class MyClass : IDisposable
{
SomeHelper helper = CreateHelper();
// ...foo and bar that now just use the class helper....
//~MyClass()
public void Dispose()
{
helper.Dispose();
}
}
现在您必须在 using 块中使用
MyClass
实例。它本身已成为托管资源。 析构函数是没有用的,每当收集 MyClass 实例时,关联的辅助对象也将位于同一个集合中。但拥有析构函数仍然会产生相当大的开销。
IDisposable 的
标准模式使用virtual void Dispose(bool disposing)
方法,但是在创建类
sealed
时,您可以使用上面的简约实现。
你根本不知道何时(或是否)调用终结器。
相反,被处置: (这正是
SomeHelper
所做的)
class MyClass : IDisposable
{
readonly SomeHelper helper = CreateHelper();
// any method can use helper
public void Dispose()
{
helper.Dispose();
}
}
using(var myObj = new MyClass()) {
// at the end, myObj.Dispose() will trigger helper.Dispose()
}
我使用
readonly
来确保
helper
不会被重新分配到班级中的其他地方,但如果你小心的话,这真的并不重要。您必须格外小心,切勿将其设置为
null
,否则您的
Dispose
将引发异常。如果该字段为
protected
,您可以在调用
Dispose
之前检查是否为空,这样您就知道自己是安全的。
实现 IDisposable。
如果你不想一直使用using,也许你可以在很多函数中使用一次。
IDisposable
对象,它也应该实现
IDisposable
。因此,您的类不应该实现终结器,而应该实现
IDisposable
并在那里处理助手。实现终结器的一个问题是您无法控制它何时被调用。一次性模式为您提供了一种更加确定的清理资源的方式。
~MyClass()
显示了该终结器。您将需要实施
IDisposable
模式。如果您使用的是托管资源和非托管资源,您的问题并没有明确说明,但这里有一个托管资源的快速示例。 Stackoverflow 有无数这方面的例子。 Reed Copsey 也有一个很好的系列,您可以从这里开始。
class MyClass : IDisposable
{
private bool _Disposed;
private SomeHelper _Helper;
protected virtual void Dispose()
{
this.Dispose(true);
}
public void Dispose(bool disposing)
{
if (_!Disposed && disposing)
{
if (_Helper != null)
_Helper.Dispose();
_Disposed = true;
}
}
}