当明确处理所有成员时,类是否需要实现IDisposable?

时间:2012-06-08 21:17:27

标签: c# .net-2.0 idisposable

试图了解何时需要实施IDisposable:

我写了一个小例子。

  public class FileManager
  {
    private FileStream fileStream;
    public void OpenFile(string path)
    {
       this.fileStream = File.Open(path, FileMode.Open, FileAccess.Read);
    }
    public void CloseFile(string path)
    {
      if ( this.fileStream != null && this.fileStream.CanRead)
      {
        this.fileStream.Close();          
      }
      this.fileStream.Dispose();
    }
  }

// client
var manager = new FileManager();
manager.Open("path");
manager.Close("path");

这个类是否需要实现IDisposable,因为它有一个托管资源(FileStream),它保存在非托管资源(文件)上?或者我不必实现IDisposable,因为我正在课堂上清理?

混淆。

6 个答案:

答案 0 :(得分:5)

对于实现IDisposable并且可能以非平凡方式执行此操作的任何类型的每个实例,它必须始终能够识别该实例将如何Dispose d。在大多数情况下,这意味着每个IDisposable实例都有一个明确定义的所有者,负责调用Dispose。对于班级创建的FileStream实例,您的班级是所有者,因为其他任何内容都无法Dispose

带有引用他们拥有的IDisposable实例 的字段的类应该几乎总是实现IDisposable,并使用他们的Dispose方法Dispose他们拥有的IDisposable个对象。你的班级有这样一个领域;因此,它应该实现IDisposable

只要有可能,应该设计一个需要清理的类,以便在其上调用IDisposable.Dispose就足以执行可能需要的任何和所有这样的清理。在某些情况下,在不使用其他方法的情况下执行清理可能是不切实际的,但这些情况非常罕见。如果可以设计一个类,以便Dispose将负责所有必要的清理,那么应该这样做。

答案 1 :(得分:1)

如果您(或其他开发人员)使用您的FileManager类而忘记关闭它,您可能希望实现IDisposable。请注意IDisposable的示例如何在终结器中调用Dispose(false)

答案 2 :(得分:1)

为什么要将路径传递给close方法?在您的情况下,似乎您的经理可以打开不同的文件,如果他们在打开另一个文件之前关闭,所以您不希望处置该对象。

恕我直言,我更愿意这样实现:

public class FileManager : IDisposable
{
    private string path;
    private FileStream fileStream;
    public FileManager(string path) 
    {
       this.path = path;
    }
    public void OpenFile()
    {
       this.fileStream = File.Open(path, FileMode.Open, FileAccess.Read);
    }
    public void CloseFile()
    {
      if ( this.fileStream != null && this.fileStream.CanRead)
      {
        this.fileStream.Close();
        this.fileStream.Dispose();
      }
    }

    public void Dispose(){
        this.CloseFile();
    }
}

// client
var manager = new FileManager("path")){
manager.OpenFile();
//Do other stuff
manager.CloseFile()

using( var manager = new FileManager("path")){
    manager.OpenFile();
    //Do other stuff
}

答案 3 :(得分:1)

如果您调用Close方法,则无需单独处理。但是,在这种情况下的一般做法是实现IDisposable,因为无法保证该类的消费者会调用​​Close

如果创建资源然后在同一方法中处置资源,您只能可靠地省略IDisposable,因为这是确保资源在使用后明确处置的唯一方法。

答案 4 :(得分:1)

您应该实现IDisposable。

想象:

var manager = new FileManager();
manager.Open("path"); // <- throws for some reason
manager.Close(); // <- then this never gets called

当然,您现在可以尝试/最终围绕它:

try {
  var manager = new FileManager();
  manager.Open("path");
}
finally {
  manager.Close();
}

...但这正是发明使用和IDisposable的原因,你可以用它来舒适地写:

using (var manager = new Manager()) {
  manager.OpenFile("path");
} // and CloseFile will automagically be called here.

答案 5 :(得分:0)

在这里实现IDisposable时,看不到任何真正的好处,如果不是声明性的话。如果有人看到你的类实现IDisposable,他就会明白在使用后必须清理某些资源。它只是一个内置的.net声明类似的类型。

如果您不使用该模式,您可以自由地执行此操作,但是您违反了建议,并且主要是针对.net类型声明的社区指南。