Does a class need to implement IDisposable when all members are explicitly disposed?

﹥>﹥吖頭↗ 提交于 2020-01-13 19:59:27

问题


Trying to understand when implementation of IDisposable is necessary:

I wrote a little example.

  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");

Does this class need to implement IDisposable because it has a managed resource (FileStream) which holds onto an unmanaged resource (a file)? Or do I not have to implement IDisposable because I am cleaning up within the class?

Confused.


回答1:


For every instance of any type which implements IDisposable and might do so in a non-trivial fashion, it must at every moment be possible to identify how that instance will be Disposed. In most cases, this means that each IDisposable instance will have a well-defined owner, which is responsible for calling Dispose. In the case of the FileStream instance created by the class, your class is the owner, since nothing else will be able to Dispose it.

Classes with fields that references to IDisposable instances which they own should almost always implement IDisposable, and use their Dispose method to Dispose the IDisposable objects they own. Your class has such a field; it should thus implement IDisposable.

Whenever possible, a class which requires cleanup should be designed so that calling IDisposable.Dispose on it will suffice to perform any and all such cleanup as may be needed. In some cases, it may be impractical to perform cleanup without using some other method, but those cases are pretty rare. If one can design a class so that Dispose will take care of all necessary cleanup, one should do so.




回答2:


You will probably want to implement IDisposable, in the event that you (or another developer) use your FileManager class and forget to close it. Note how the example for IDisposable puts a call to Dispose(false) in the finalizer.




回答3:


Why are you passing the path to the close method? In your case, it seems your manager can open different files if they are close before opening another one, so you won't want to dispose that object.

IMHO, I would prefer to implement it this way:

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

or

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



回答4:


In the case that you call your Close method, you don't need to separately dispose. However, general practise in this case would be to implement IDisposable because there's no guarantee that a consumer of the class would call Close.

You can only reliably leave out IDisposable if a resource is created and then disposed within the same method, because that's the only way you can be sure that the resource is definitely disposed of after use.




回答5:


You should implement IDisposable.

Imagine:

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

Of course you could now put a try/finally around it like that:

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

... but that's exactly what using and IDisposable have been invented for, with which you can comfy write:

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



回答6:


Don't see any real benefits in implementing IDisposable here, if not declarative ones. If someone sees your class implements IDisposable he understands that there are somewhere resources that have to be cleaned up after use. It's just a built-in .net convension of declaring types like this.

If you don't use that pattern, you are free to do that , but you violate suggested and mainly followed by community guidelunes for .net type declaration.



来源:https://stackoverflow.com/questions/10956140/does-a-class-need-to-implement-idisposable-when-all-members-are-explicitly-dispo

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!