关闭或释放资源

37

StreamReader类有close和dispose方法,我想知道应该调用哪个方法来清理所有资源。

如果使用using块,我认为它将调用其dispose方法。这样做是否足以清理所有资源。


2
https://dev59.com/AHVD5IYBdhLWcg3wL4cA - Oleks
6个回答

31
using块将在StreamReader实例上调用Dispose()方法。一般来说,如果一个类型是IDisposable,你应该将其放在using作用域内。

编辑:如果你使用Reflector查看StreamReaderClose()实现,你会发现它调用了Dispose(true)。因此,如果你没有使用using作用域,在这种特定情况下手动调用Close()将等同于调用Dispose()

protected override void Dispose(bool disposing)
{
    try
    {
        if ((this.Closable && disposing) && (this.stream != null))
        {
            this.stream.Close();
        }
    }
    finally
    {
        if (this.Closable && (this.stream != null))
        {
            this.stream = null;
            this.encoding = null;
            this.decoder = null;
            this.byteBuffer = null;
            this.charBuffer = null;
            this.charPos = 0;
            this.charLen = 0;
            base.Dispose(disposing);
        }
    }
}

1
close calls dispose(true),使用using块也会调用dispose(true)吗? - user496949
1
这就解释了为什么如果你在using语句块中有一个调用Close()的代码,在运行Visual Studio的代码分析时,你会得到CA2202不要多次处理对象的警告 - 因为Close()已经处理了对象,而using最终也会尝试处理该对象。那么我想知道...为什么我们实际上并没有遇到System.ObjectDisposedException异常。 - Veverke
@Veverke,Close方法会释放对象,但不会标记为已释放,这就是为什么它不会抛出System.ObjectDisposedException的原因。 - Anoop H.N

7
我们都知道 System.IO.StreamReader 不是唯一一个实现 IDisposableClose() 方法的 .NET 4.0+ 类。对于这个问题中的 StreamReader,源代码显示基类 TextReader.Close()TextReader.Dispose() 都运行相同的代码行。您还可以在代码中看到,TextReader.Dispose() 是当您调用 StreamReader.Dispose() 时的实现(因为 StreamReader 没有覆盖那个方法重载签名的 Dispose)。

因此,对 StreamReader.Dispose() 的调用将运行 这个继承代码行, 它调用了受保护的重写方法 StreamReader.Dispose(disposing: true),所以 StreamReader.Close() 也会调用 StreamReader.Dispose(disposing: true)。因此,对于 StreamReaderClose()Dispose() 确实运行相同的代码行。

一个更一般的、非类特定的答案是关于 Close() 还是 Dispose()? 的问题,可能需要注意到微软在实现 IDisposable 和 Dispose 模式方面有相当清晰的 文档。快速阅读足以向您展示实现 Close() 方法不是 Dispose 模式的要求。

在我看来,实现IDisposable接口的许多类中都有Close()方法是由于惯例而非要求所致。

有人评论说:

Close和Dispose-哪个需要调用?

这是另一个实现了Dispose模式并具有Close()方法的类的示例。在这种情况下,Close()方法是否运行与Dispose()相同的代码?我还没有查看源代码,但我认为不一定。


2

使用using块来通过Dispose保证清理工作的进行。

如果你在using块结束之前大幅度完成了对象的操作,使用Close可以尽可能迅速地释放任何资源。

这两个方法将相互协作,但是如果你无论如何都会在几纳秒内到达块的末尾,后者可能会是多余的。


1

使用块就是你所需要的一切。


使用 using 语句将保证调用 dispose 方法。这和调用 close 方法一样吗? - user496949
dispose 会隐式关闭流。 - Stefan P.
除非你编写的是具有长生命周期的“复杂”代码,否则更好的建议是:如果在语法上可行,则使用using。否则,像一个大孩子一样小心地处理编程世界自内存分配发明以来就一直面对的复杂性。 - Eliot Gillum

1

如果您想了解更多关于使用的信息,请查看这里

使用

来自网站的引用:

using语句允许程序员指定使用资源的对象何时释放它们。提供给using语句的对象必须实现IDisposable接口。该接口提供Dispose方法,应该释放对象的资源。


1

有一些人担心Dispose是否能够正确地执行其工作。

本质上 - 您可以相当确定在实现IDisposable的BCL(基础类库)中的任何东西在调用dispose时都会适当地清理自己 - 例如,当使用语句超出范围时。

如果存在未关闭的流的问题,它们将被发现-您可以信任IDisposable。 当您使用其他库依赖于Dispose实现时,情况就不同了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接