Naw*_*waz 139 c# idisposable stream streamwriter streamreader
类如Stream,StreamReader,StreamWriter等工具IDisposable界面.这意味着,我们可以Dispose()在这些类的对象上调用方法.他们还定义了一个public名为的方法Close().现在让我感到困惑的是,一旦我完成了对象,我该怎么称呼?如果我同时打电话怎么办?
我目前的代码是这样的:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,我编写了using()构造,自动调用Dispose()每个对象的方法.但我也称之为Close()方法.这样对吗?
请告诉我使用流对象时的最佳做法.:-)
MSDN示例不使用using()构造,并且调用Close()方法:
好吗?
Eni*_*ity 96
快速跳转到Reflector.NET显示该Close()方法StreamWriter是:
public override void Close()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
Run Code Online (Sandbox Code Playgroud)
并且StreamReader是:
public override void Close()
{
this.Dispose(true);
}
Run Code Online (Sandbox Code Playgroud)
该Dispose(bool disposing)超控StreamReader是:
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
的StreamWriter方法是相似的.
因此,阅读代码很明显,您可以根据自己的喜好和任何顺序随时调用Close()&Dispose().它不会以任何方式改变行为.
所以它归结为它是否是更具可读性使用Dispose(),Close()和/或using ( ... ) { ... }.
我个人的偏好是using ( ... ) { ... }应尽可能使用,因为它可以帮助你"不用剪刀".
但是,虽然这有助于正确性,但确实会降低可读性.在C#中,我们已经有了大量的花括号,所以我们怎么知道哪一个实际上在流上执行了关闭呢?
所以我认为最好这样做:
using (var stream = ...)
{
/* code */
stream.Close();
}
Run Code Online (Sandbox Code Playgroud)
它不会影响代码的行为,但它确实有助于提高可读性.
Dar*_*rov 45
不,你不应该手动调用这些方法.在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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
Close方法调用Dispose.
Joe*_*nta 21
无论如何,源代码Stream.Close解释了为什么有两种方法:
Run Code Online (Sandbox Code Playgroud)// 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,并且出于兼容性原因无法将其删除。
Hei*_*nzi 12
文档说这两种方法是等价的:
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();
}
Run Code Online (Sandbox Code Playgroud)
就个人而言,我会坚持使用第一个选项,因为它包含较少的"噪音".
这是一个老问题,但您现在可以编写 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);
}
}
Run Code Online (Sandbox Code Playgroud)
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/using
在许多同时支持Close()和Dispose()方法的类上,这两个调用是等效的。但是,在某些类上,可以重新打开已关闭的对象。一些这样的类可能会在关闭后保持一些资源处于活动状态,以允许重新打开;其他人可能不会在 上保持任何资源处于活动状态Close(),但可能会设置一个标志Dispose()来明确禁止重新打开。
的契约IDisposable.Dispose明确要求在一个永远不会再次使用的对象上调用它在最坏的情况下是无害的,所以我建议在每个对象上调用一个IDisposable.Dispose或一个方法,无论Dispose()一个IDisposable对象是否也调用Close().