我应该为流对象调用Close()还是Dispose()吗?
本文关键字:还是 Dispose Close 对象 调用 我应该 | 更新日期: 2023-09-27 18:09:22
Stream
、StreamReader
、StreamWriter
等类实现了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()
方法。对吗?
请告诉我使用流对象的最佳实践。: -)
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);
}
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()
上的流,经常你喜欢和在任何顺序。它不会以任何方式改变行为。
所以这取决于是否使用Dispose()
, Close()
和/或using ( ... ) { ... }
更可读。
我个人的偏好是using ( ... ) { ... }
应该尽可能地使用,因为它可以帮助你"不带着剪刀跑"。
所以我认为最好这样做:
using (var stream = ...)
{
/* code */
stream.Close();
}
它不影响代码的行为,但它有助于可读性。
不,您不应该手动调用这些方法。在using
块的末尾,自动调用Dispose()
方法,它将负责释放非托管资源(至少对于标准。net BCL类,如流,读取器/写入器,…)。所以你也可以这样写你的代码:
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的实现调用Dispose方法,传递一个真值。
流。Close:该方法调用Dispose,指定true释放所有资源。
所以,这两个是同样有效的:
/* Option 1, implicitly calling Dispose */
using (StreamWriter writer = new StreamWriter(filename)) {
// do something
}
/* Option 2, explicitly calling Close */
StreamWriter writer = new StreamWriter(filename)
try {
// do something
}
finally {
writer.Close();
}
就我个人而言,我会坚持使用第一个选项,因为它包含较少的"噪音"。
无论如何,Stream.Close
的源代码解释了为什么有两个方法:
// Stream used to require that all cleanup logic went into Close(), // which was thought up before we invented IDisposable. However, we // need to follow the IDisposable pattern so that users can write // sensible subclasses without needing to inspect all their base // classes, and without worrying about version brittleness, from a // base class switching to the Dispose pattern. We're moving // Stream to the Dispose(bool) pattern - that's where all subclasses // should put their cleanup now.
简而言之,Close
的存在只是因为它早于Dispose
,由于兼容性原因,它不能被删除。
这是一个老问题,但是你现在可以( c# 8.0)编写using
语句而不需要阻塞每个语句。当包含块完成时,它们将以相反的顺序被处理。
using var responseStream = response.GetResponseStream();
using var reader = new StreamReader(responseStream);
using var 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);
}
}
https://learn.microsoft.com/en - us/dotnet/csharp/language reference/proposals/csharp - 8.0 -/-使用
在许多同时支持Close()
和Dispose()
方法的类中,这两个调用将是等效的。但是,在某些类上,可以重新打开已关闭的对象。一些这样的类可能会在关闭后保留一些资源,以便允许重新打开;其他可能不会在Close()
上保留任何资源,但可能会在Dispose()
上设置一个标志来明确禁止重新打开。
IDisposable.Dispose
的契约明确要求在一个永远不会再使用的对象上调用它是无害的,所以我建议在每个IDisposable
对象上调用IDisposable.Dispose
或一个名为Dispose()
的方法,无论是否也调用Close()
。
只是为了补充其他答案,从c# 8.0开始,您不需要打开代码块来使用using
语句
if (...)
{
using FileStream f = new FileStream(@"C:'users'jaredpar'using.md");
// statements
}
// Equivalent to
if (...)
{
using (FileStream f = new FileStream(@"C:'users'jaredpar'using.md"))
{
// statements
}
}
文档:
https://learn.microsoft.com/en - us/dotnet/csharp/language reference/proposals/csharp - 8.0 -/-使用