基本上我有一些看起来像这样的函数:
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();
}
}
答案 0 :(得分:8)
不,请不添加析构函数(Finalizer)。
您可以重复使用该资源,但您的类必须实现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的standard pattern使用virtual void Dispose(bool disposing)
方法,但在制作课程sealed
时,您可以使用上面的简约实现。
答案 1 :(得分:2)
在.NET you don't know when (or whether) finalizer is called中。
相反,明确指出implementing IDisposable
要处理您的课程:
(这正是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
之前检查是否为空,这样您就知道自己正在安全地玩。
答案 2 :(得分:1)
您可以在对象的生命周期内共享此类资源,在这种情况下,建议您implement IDisposable。
答案 3 :(得分:1)
惯例是,如果您的类拥有IDisposable
对象,它还应该实现IDisposable
。因此,不是实现终结器,而是应该在那里实现IDisposable
和帮助器的实现。
实现终结器的一个问题是你无法控制它何时被调用。一次性模式为您提供了更加确定的清理资源的方式。
答案 4 :(得分:1)
不,不是。你不知道什么时候最终确定。此外,如果您的资源是受管理的,那么它将在某些时候被处理掉,而不会被最终确定。
如果您不想一直使用,也许您可以在许多功能周围使用它。
答案 5 :(得分:1)
您无需覆盖对象中的终结器,您已在第二个代码示例中显示~MyClass()
。
您需要实施IDisposable
模式。如果您使用的是托管和非托管资源,那么您的问题并未明确,但这里是托管资源的快速示例。 Stackoverflow有很多这方面的例子。 Reed Copsey也有一个很好的系列,你可以开始here。
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;
}
}
}