使用()并使用多个包装流进行处理

时间:2009-08-03 18:47:50

标签: c# stream dispose

我是对的,如果你正在做的话,你只需要在最外面的流中使用using()

MemoryStream mstr = new MemoryStream();

using(StreamWriter w = new StreamWriter(mstr)) {
    ....
}

由于处理StreamWriter还应该处理/关闭底层流,没有必要这样做?:

using(MemoryStream mstr = new MemoryStream())
using(StreamWriter w = new StreamWriter(mstr)) {
    ....
}

(注意这些只是示例,关于如何处理包装的流,而不是像使用StringWriter等那样寻找替代方案。)

5 个答案:

答案 0 :(得分:9)

从可读性和可维护性的角度出发,将所有依赖资源放在自己的using块中是一个好主意。例如在下面的代码中,在最后一个括号之后,不可能尝试访问mstr,因为它的范围限定在有效的块内:

using (MemoryStream mstr = new MemoryStream())
using (StreamWriter w = new StreamWriter(mstr) {
    ....
}

// cannot attempt to access mstr here

如果你没有这样的范围,那么仍然可以在有效范围之外访问mstr

MemoryStream mstr = new MemoryStream();
using (StreamWriter w = new StreamWriter(mstr) {
    ....
}

mstr.Write(...); // KABOOM! ObjectDisposedException occurs here!

因此虽然它可能并不总是必要的(并且在这种情况下它不是),但这是一个好主意,因为它既澄清并强制执行你对其范围的意图。

答案 1 :(得分:7)

我的经验法则:如果它实现了IDisposable,请将其丢弃。

当前(可能永远),调用StreamWriter.Dispose()关闭基础流,您将来可能使用的其他流派生类可能不会。此外,它似乎也没有实际调用Dispose(),因此非MemoryStreams可能无法正确处理(尽管我现在无法想到任何会受到影响的东西)。

因此,虽然可以只能安全地处理StreamWriter,但我发现在可能的情况下始终使用块用于一次性用品是一种更好的做法。

答案 2 :(得分:4)

通过查看Reflector中的StreamWriter.Dispose方法,看起来底层流已关闭,但未被丢弃。我会将每个流放在一个“使用”块中,以便明确地处理它们。

答案 3 :(得分:3)

回答你的实际问题。 TextWriter的Dispose方法

public void Dispose()
{
    this.Dispose(true);
    GC.SuppressFinalize(this);
}

它调用受保护的Dispose并将true传递给它。来自TextWriter.Dispose Method (Boolean)

  

当处置参数为 true 时,   此方法释放所有资源   由任何托管对象持有这个   TextWriter引用。 此方法   调用每个的Dispose方法   引用对象。

然而,最好将实现IDisposable的所有内容包装在using块中,因为我们无法保证始终使用 true 参数调用受保护的Dipose方法。

答案 4 :(得分:0)

总是使用using阻止这是一种更好的做法。

“总是”,除了一个众所周知的WCF代理类的情况,其中设计缺陷有时会导致其Dispose方法抛出异常,从而丢失原始异常。