在每个函数中使用语句->通过适当的清理转换为类字段
本文关键字:转换 字段 函数 语句 | 更新日期: 2023-09-27 18:15:37
基本上我有几个函数看起来像这样:
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();
}
}
不,不要添加析构函数(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
实例。它本身已经成为一个管理的资源。
IDisposable的标准模式使用virtual void Dispose(bool disposing)
方法,但是当创建sealed
类时,您可以使用上面的最小化实现。
在。net中,你根本不知道何时(或是否)调用了终结器。
相反,显式地指示您的类将通过实现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
之前检查它是否为空,这样你就知道你是安全的。
您可以在对象的生命周期内共享这样的资源,在这种情况下,建议您实现IDisposable。
不,不是。你不知道什么时候会结束。此外,如果您的资源是托管的,它将在某个时候被处置,而不最终确定。
如果你不想一直使用using,也许你可以在多个函数中使用一次。
您不需要重写对象中的终结器,这在~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;
}
}
}
约定是,如果你的类拥有一个IDisposable
对象,它也应该实现IDisposable
。因此,你的类应该实现IDisposable
,而不是实现终结器,并在那里处理帮助器。
实现终结器的一个问题是你无法控制何时调用它。一次性模式为您提供了一种更确定的清理资源的方式。