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

时间:2011-11-22 18:16:23

标签: c# .net idisposable

基本上我有一些看起来像这样的函数:

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();
    }
}

6 个答案:

答案 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;
     }
   }
}