在每个函数中使用语句->通过适当的清理转换为类字段

本文关键字:转换 字段 函数 语句 | 更新日期: 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实例。它本身已经成为一个管理的资源

析构函数是没有用的,每当收集MyClass实例时,相关的helper对象也将在同一个集合中。但是使用析构函数仍然会产生相当大的开销。

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,而不是实现终结器,并在那里处理帮助器。

实现终结器的一个问题是你无法控制何时调用它。一次性模式为您提供了一种更确定的清理资源的方式。