当所有成员都被明确处理时,类是否需要实现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类型声明的社区指南。