问题描述
Stream、StreamReader、StreamWriter 等类实现了IDisposable 接口.这意味着,我们可以对这些类的对象调用 Dispose() 方法.他们还定义了一个名为 Close() 的 public 方法.现在这让我很困惑,一旦我完成了对象,我应该调用什么?如果我同时调用两者呢?
Classes such as Stream, StreamReader, StreamWriter etc implements IDisposable interface. That means, we can call Dispose() method on objects of these classes. They've also defined a public method called Close(). Now that confuses me, as to what should I call once I'm done with objects? What if I call both?
我当前的代码是这样的:
My current code is this:
using (Stream responseStream = response.GetResponseStream()) { using (StreamReader reader = new StreamReader(responseStream)) { using (StreamWriter writer = new StreamWriter(filename)) { int chunkSize = 1024; while (!reader.EndOfStream) { char[] buffer = new char[chunkSize]; int count = reader.Read(buffer, 0, chunkSize); if (count != 0) { writer.Write(buffer, 0, count); } } writer.Close(); } reader.Close(); } }
如您所见,我编写了 using() 构造,它会自动调用每个对象上的 Dispose() 方法.但我也调用了 Close() 方法.是吗?
As you see, I've written using() constructs, which automatically call Dispose() method on each object. But I also call Close() methods. Is it right?
请建议我使用流对象时的最佳实践.:-)
Please suggest me the best practices when using stream objects. :-)
MSDN 示例不使用 using() 构造,并调用 Close() 方法:
MSDN example doesn't use using() constructs, and call Close() method:
- 如何:使用 FTP 下载文件
好用吗?
推荐答案
快速跳转到 Reflector.NET 可以看到 StreamWriter 上的 Close() 方法是:
A quick jump into Reflector.NET shows that the Close() method on StreamWriter is:
public override void Close() { this.Dispose(true); GC.SuppressFinalize(this); }
而 StreamReader 是:
public override void Close() { this.Dispose(true); }
StreamReader 中的 Dispose(bool disposing) 覆盖是:
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; /* deleted for brevity */ base.Dispose(disposing); } } }
StreamWriter 方法类似.
所以,阅读代码很明显你可以调用 Close() &Dispose() 在流上按您喜欢的频率和顺序.它不会以任何方式改变行为.
So, reading the code it is clear that that you can call Close() & Dispose() on streams as often as you like and in any order. It won't change the behaviour in any way.
所以这归结为使用 Dispose()、Close() 和/或 using ( ... ){ ... }.
So it comes down to whether or not it is more readable to use Dispose(), Close() and/or using ( ... ) { ... }.
我个人的偏好是 using ( ... ) { ... } 应该尽可能使用,因为它可以帮助你不用剪刀跑".
My personal preference is that using ( ... ) { ... } should always be used when possible as it helps you to "not run with scissors".
但是,虽然这有助于正确性,但它确实降低了可读性.在 C# 中,我们已经有过多的关闭花括号,那么我们如何知道哪个真正在流上执行了关闭?
But, while this helps correctness, it does reduce readability. In C# we already have plethora of closing curly braces so how do we know which one actually performs the close on the stream?
所以我认为最好这样做:
So I think it is best to do this:
using (var stream = ...) { /* code */ stream.Close(); }
它不会影响代码的行为,但确实有助于提高可读性.
It doesn't affect the behaviour of the code, but it does aid readability.