问题
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 Dispose
d. 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