我真的需要调用 FileStream 吗?Close/Dispose

Do I actually need to call FileStream.Close/Dispose

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

我真的需要这样做吗?

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

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

我可以想象,C# 中的垃圾收集器非常适合 GC,以响应吞噬文件句柄等系统资源的程序。即使没有,我可以想象打开的文件句柄在现代服务器中基本上是免费的 OS.

那么调用 Dispose 是不是很迂腐?

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

如果您使用托管资源,它应该(最终)由 GC 清理,并且您可以决定是否使用它,但它提供了一个很好的语法糖来处理非托管资源,方法是通用接口。

我认为关于 IDisposable 的数十个或数百个现有问题很好地涵盖了这个问题。也就是说,解决您的具体问题:

  1. "I assume that the garbage collector is smart enough to call Dispose for me on any object that is IDisposable. Is that true?"

是也不是。实现 IDisposable 的对象通常也实现终结器。是 that 导致 GC 在收集之前处理对象。

请注意,在处理终结器时会产生大量开销,如果显式处置对象,这些开销就会被抑制。仅此一点就足以证明您正确处理对象是合理的。

  1. "I may be creating a lot of file handles. Is this actually a problem?"

是的,这实际上是一个问题。 Windows 现在比以前有更多的句柄 table space,但它仍然是一个受限的资源。

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

  1. "So is calling Dispose being pedantic?"

没有。在实现 IDisposable 的对象(您拥有并且知​​道不再需要使用的对象)上调用 Dispose() 是任何正确程序的重要组成部分。