Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当显式释放所有成员时,类是否需要实现IDisposable?_C#_.net 2.0_Idisposable - Fatal编程技术网

C# 当显式释放所有成员时,类是否需要实现IDisposable?

C# 当显式释放所有成员时,类是否需要实现IDisposable?,c#,.net-2.0,idisposable,C#,.net 2.0,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(st

试图了解何时需要实施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
没有任何真正的好处。如果有人看到您的类实现了
IDisposable
,他就会明白,在某些地方,资源在使用后必须清理。它只是一个内置的
.net
声明类型的约定,就像这样


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

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

为什么要将路径传递给close方法?在您的情况下,如果在打开另一个文件之前关闭了不同的文件,则您的经理似乎可以打开这些文件,因此您不想处理该对象

IMHO,我更愿意这样实施:

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


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


如果资源是在同一方法中创建并释放的,则只能可靠地省略
IDisposable
,因为这是确保资源在使用后确实被释放的唯一方法。

您应该实现IDisposable

想象一下:

var manager = new FileManager();
manager.Open("path"); // <- throws for some reason
manager.Close(); // <- then this never gets called
。。。但这正是发明using和IDisposable的目的,你可以轻松地写:

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

对于实现
IDisposable
且可能以非平凡方式实现的任何类型的每个实例,必须随时能够确定该实例将如何
处置
d。在大多数情况下,这意味着每个
IDisposable
实例都有一个定义良好的所有者,负责调用
Dispose
。在类创建的
FileStream
实例中,您的类是所有者,因为没有其他东西能够
处置它

具有引用自己的
IDisposable
实例的字段的类应该几乎总是实现
IDisposable
,并使用其
Dispose
方法来
Dispose
它们所拥有的
IDisposable
对象。你们班有这样一个领域;因此,它应该实现
IDisposable


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

在调用
管理器.Close
之前引发异常时会发生什么情况?如果有疑问,运行FxCop-它检测并解释何时何地需要实现Dispose。@TimSchmelter-读了几遍,它看起来就像一个没有任何解决方案的参数。我没有看到任何答案@白ジェームス: 因此,我发布的链接只是作为补充,而不是重复或回答。这是我在大约5分钟内写的一个小样本,以帮助回答我的问题。我不打算用这个。答案和往常一样是“视情况而定”。因此,对于您提供的代码,这是我的答案。如果您有其他代码,我可以帮助您进行设计,看看实现
IDisposable
是否合适。这件事没有黑白之分。有时实现
IDisposable
是有意义的,有时则不然。+1我无意用示例代码来处理假设情况,但这一点很好@白ジェームス 错误处理完全是关于假设情况。。您必须始终假设在打开资源时或之后的某个时刻可能会抛出异常,并且必须为用户提供一种优雅地处理异常的方法。您可以通过try/finally“让他”这样做,或者通过实现IDisposable允许他使用“using”。人们会感谢你的。:)我想我是想说这是示例代码,只是用来帮助说明我的问题。在示例代码中,正在调用.Close,没有异常:)。这就是我要寻找的答案类型@白ジェームス: 很高兴它有用。我对那些建议类不应该实现
IDisposable
的人感到有些恼火,如果它们使用其他方法进行清理,或者如果它们的清理需要执行通常与
IDisposable
无关的操作。
IDisposable
的全部意义在于能够说(1)创建需要清理的对象的人不必研究如何清理它——只需调用
IDisposable.Dispose
;(2) 一个在其生命周期中拥有
IDisposable
对象的类通常不必担心@白ジェームス: ...它将如何发现消费者何时使用完它,因为无论是谁创建了它,都应该调用
IDisposable.Dispose
,或者将责任移交给其他某个对象,该对象的合同规定将调用
IDisposable.Dispose
。当然,有可能在一个实体
try {
  var manager = new FileManager();
  manager.Open("path");
}
finally {
  manager.Close();
}
using (var manager = new Manager()) {
  manager.OpenFile("path");
} // and CloseFile will automagically be called here.