当所有成员都被明确处理时,类是否需要实现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,因为我在课堂上清理?
困惑。
对于实现IDisposable
的任何类型的每个实例,并且可能以非平凡的方式执行,它必须在每个时刻都能够识别该实例将如何Dispose
。 在大多数情况下,这意味着每个IDisposable
实例都有一个明确定义的所有者,它负责调用Dispose
。 对于由类创建的FileStream
实例,您的类是所有者,因为没有其他任何东西能够Dispose
它。
具有引用它们所拥有的 IDisposable
实例的字段的类几乎总是实现IDisposable
,并使用它们的Dispose
方法来Dispose
它们拥有的IDisposable
对象。 你的class级有这样一个领域; 因此它应该实现IDisposable
。
只要有可能,应该设计一个需要清理的类,以便在其上调用IDisposable.Dispose
就足以执行可能需要的任何和所有这样的清理。 在某些情况下,在不使用其他方法的情况下执行清理可能是不切实际的,但这些情况非常罕见。 如果可以设计一个类以便Dispose
将负责所有必要的清理,那么应该这样做。
如果您(或其他开发人员)使用您的FileManager类而忘记关闭它,您可能希望实现IDisposable。 请注意IDisposable的示例如何在终结器中调用Dispose(false)
。
为什么要将路径传递给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 }
如果您调用Close
方法,则无需单独处理。 但是,在这种情况下的一般做法是实现IDisposable
因为不能保证类的使用者会调用Close
。
如果创建资源然后在同一方法中处理,您只能可靠地省略IDisposable
,因为这是确保资源在使用后绝对处理掉的唯一方法。
你应该实现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.
在这里实现IDisposable
看不到任何实际好处,如果不是声明性的话。 如果有人看到你的类实现了IDisposable
他就知道有一些资源必须在使用后清理掉。 它只是一个内置的.net
传播,声明这样的类型。
如果您不使用该模式,则可以自由地执行此操作,但是您违反了建议,并且主要遵循.net
类型声明的社区指南。