我应该为stream对象调用Close()还是Dispose()?

StreamStreamReaderStreamWriter等类实现了IDisposable接口。 这意味着,我们可以在这些类的对象上调用Dispose()方法。 他们还定义了一个名为Close()public方法。 现在,让我感到困惑的是,一旦我完成了对象,我该怎么称呼? 如果我同时打电话呢?

我目前的代码是这样的:

 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()方法。 这样对吗?

请build议我使用stream对象的最佳做法。 🙂

MSDN示例不使用using()构造,并调用Close()方法:

  • 如何:使用FTP下载文件

好吗?

快速跳转到Reflector.NET显示StreamWriter上的Close()方法是:

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

StreamReader是:

 public override void Close() { this.Dispose(true); } 

StreamReaderDispose(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方法类似。

因此,阅读代码很明显,您可以按照您的喜好和任何顺序经常在stream上调用Close()Dispose() 。 它不会以任何方式改变行为。

所以最终归结为使用Dispose()Close()和/或using ( ... ) { ... }是否更具可读性。

我个人的偏好是using ( ... ) { ... }应该尽可能使用,因为它可以帮助你“不用剪刀运行”。

但是,虽然这有助于正确性,但确实降低了可读性。 在C#中,我们已经有了大量的大括号,所以我们怎么知道哪一个实际执行了closures的stream?

所以我认为最好这样做:

 using (var stream = ...) { /* code */ stream.Close(); } 

它不会影响代码的行为,但确实有助于可读性。

不,你不应该手动调用这些方法。 在using块结束时,将自动调用Dispose方法,这将自动调用释放非托pipe资源(至less对于标准的.NET BCL类,如stream,读者/作者…)。 所以你也可以这样写你的代码:

 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); } } } 

Close方法调用Dispose。

文档说这两个方法是等价的:

StreamReader.Close :Close的这个实现调用了传递一个真实值的Dispose方法。

StreamWriter.Close :Close的这个实现调用Dispose方法传递一个真实的值。

Stream.Close :此方法调用Dispose,指定true以释放所有资源。

所以,这两个都是同样有效的:

 /* Option 1 */ using (StreamWriter writer = new StreamWriter(filename)) { // do something } /* Option 2 */ StreamWriter writer = new StreamWriter(filename) try { // do something } finally { writer.Close(); } 

就个人而言,我会坚持第一个选项,因为它包含较less的“噪音”。

在许多支持Close和Dispose方法的类上,这两个调用将是等价的。 然而,在某些类别中,可能会重新打开已closures的对象。 一些这样的类可能在closures之后保留一些资源,以便允许重新打开; 其他人在closures时可能不会保留任何资源,但可能会在Dispose上设置一个标志来明确禁止重新打开。

IDisposable.Dispose的契约明确要求在一个永远不会被再次使用的对象上调用它是最坏的,所以我build议在每个IDisposable对象上调用IDisposable.Dispose或Dispose方法,无论是否还有来电closures。