我是否真的需要调用FileStream.Close / Dispose

时间:2015-01-08 01:43:35

标签: c# garbage-collection

我看到很多示例代码将FileStream包含在using块中,或者显式调用Dispose()。

我真的需要这样做吗?

在我(可能是简单的)理解中,C#是一种垃圾收集语言,当一个对象超出范围时,它被标记为收集。我假设垃圾收集器足够聪明,可以在任何IDisposable对象上为我调用Dispose。这是真的吗?

此外,我了解C#中的GC是非确定性的,并且出于性能原因,不会直接响应超出范围的对象。所以,如果我每秒打开一百万个文件而不是处理它们,我可能会创建很多文件句柄。这实际上是个问题吗?

我可以想象C#中的垃圾收集器对于响应一个吞噬系统资源(如文件句柄)的程序而言非常花哨。即使它没有,我可以想象在现代服务器操作系统中,打开文件句柄基本上是免费的。

所谓调用Dispose是迂腐吗?

2 个答案:

答案 0 :(得分:4)

我认为关于IDisposable的几十个或几百个现有问题可以很好地解决这个问题。那说,解决你的具体问题:

  1. "我假设垃圾收集器足够智能,可以在任何IDisposable对象上为我调用Dispose。这是真的吗?"
  2. 是和否。实现IDisposable的对象通常也会实现终结器。它的 会导致GC在收集对象之前处置它。

    请注意,处理终结器会产生很大的开销,如果您明确地处理对象,则会抑制开销。只有这一点才足以证明你确保正确处理对象。

    1. "我可能正在创建大量文件句柄。这实际上是一个问题吗?"
    2. 是的,这实际上是一个问题。 Windows现在拥有比以往更多的句柄表空间,但它仍然是一个受限制的资源。

      此外,文件仍然打开,直到句柄关闭。这可能会阻止其他进程在需要时访问该文件,或者可能允许在刷新文件之前访问该文件,因此文件写入不完整。

      1. "所以称Dispose是迂腐的?"
      2. 没有。在对象(您拥有并且不再需要使用)上调用Dispose(),实现IDisposable是任何正确程序的重要组成部分。

答案 1 :(得分:-3)

如果我没记错的话,using块只会为大括号内的任何内容分配一个对象。这需要创建的对象实现IDisposable,该目标旨在释放 un 托管资源。

如果您使用托管资源,它应该(最终)被GC清理,并且您是否使用它的调用,但它提供了一个很好的语法糖,通过一个共同的方式处理非托管资源接口