2

尝试了解何时需要实施 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 因为我在课堂上进行清理?

使困惑。

4

6 回答 6

5

对于任何类型的每个实例,它实现IDisposable并可能以一种非平凡的方式实现,它必须在每一刻都可以识别该实例将如何被Disposed。在大多数情况下,这意味着每个IDisposable实例都有一个定义明确的所有者,负责调用Dispose. 在FileStream类创建的实例的情况下,您的类是所有者,因为没有其他东西可以做到Dispose这一点。

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

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

于 2012-06-08T21:37:19.403 回答
1

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

于 2012-06-08T21:23:51.720 回答
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
}
于 2012-06-08T21:23:55.863 回答
1

如果你调用你的Close方法,你不需要单独处理。但是,在这种情况下,一般做法是实现IDisposable,因为不能保证该类的使用者会调用Close.

只有在创建资源然后在同一方法中处理资源时,您才能可靠地省略IDisposable,因为这是您可以确保资源在使用后被明确处理的唯一方法。

于 2012-06-08T21:24:41.120 回答
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();
}

...但这正是 using 和 IDisposable 的发明目的,您可以轻松地编写:

using (var manager = new Manager()) {
  manager.OpenFile("path");
} // and CloseFile will automagically be called here.
于 2012-06-08T21:31:10.317 回答
0

如果不是声明性的,在这里实施也看不到任何真正的好处。IDisposable如果有人看到你的类实现IDisposable,他就会明白有些地方需要在使用后清理资源。它只是像这样声明类型的内置.net约定。

如果您不使用该模式,则可以自由地这样做,但是您违反了建议的并且主要遵循社区指南的.net类型声明。

于 2012-06-08T21:22:41.747 回答