Answers:
是的,StreamReader
和StreamWriter
,当您调用它们时BinaryReader
,BinaryWriter
所有它们都会关闭/处置其基础流Dispose
。如果读取器/写入器只是垃圾回收,则它们不会处理流-您应该始终处理读取器/写入器,最好使用using
语句。(实际上,这些类都不具有终结器,也不应该具有终结器。)
就个人而言,我也希望对流也具有using语句。您可以using
整齐地嵌套语句而无需大括号:
using (Stream stream = ...)
using (StreamReader reader = new StreamReader(stream, Encoding.Whatever))
{
}
即使using
该流的语句有点多余(除非StreamReader
构造函数抛出异常),我还是将其视为最佳实践,因为如果您摆脱了StreamReader
并在以后直接使用该流,那么您已经可以正确处理语义。
CA2202 : Microsoft.Usage : Object 'stream' can be disposed more than once in method '...'. To avoid generating a System.ObjectDisposedException you should not call Dispose more than one time on an object.
是否应该忽略它?到目前为止,我没有任何例外...
StreamReader
。该警告对我来说似乎是虚假的,因为docs IDisposable.Dispose
明确声明:“如果对象的Dispose方法被多次调用,则该对象必须在第一个调用之后忽略所有调用。如果对象的Dispose方法为被多次呼叫。”
这是一个旧的,但是我今天想做类似的事情,发现情况已经改变。从.net 4.5开始,有一个leaveOpen
参数:
public StreamReader( Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize, bool leaveOpen )
唯一的问题是,为其他参数设置什么并不完全明显。这里有一些帮助:
从msdn页的StreamReader构造函数(Stream):
此构造函数将编码初始化为UTF8Encoding,使用stream参数将BaseStream属性初始化,并将内部缓冲区大小初始化为1024字节。
这只是叶detectEncodingFromByteOrderMarks
其判断由源代码是true
public StreamReader(Stream stream)
: this(stream, true) {
}
public StreamReader(Stream stream, bool detectEncodingFromByteOrderMarks)
: this(stream, Encoding.UTF8, detectEncodingFromByteOrderMarks, DefaultBufferSize) {
}
如果公开了其中一些默认值,或者这些参数是可选的,那么我们就可以指定所需的默认值了。
using (var streamReader = new StreamReader(myStream, Encoding.UTF8, true, 1024, true))
是的,它确实。您可以通过查看Reflector的实现来验证这一点。
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;
this.encoding = null;
this.decoder = null;
this.byteBuffer = null;
this.charBuffer = null;
this.charPos = 0;
this.charLen = 0;
base.Dispose(disposing);
}
}
}
迟了六年,但这也许会对某人有所帮助。
StreamReader在处理连接时会关闭连接。但是,在StreamReader / StreamWriter中“使用(Stream stream = ...){...}”可能导致Stream被处置两次:(1)处置StreamReader对象时(2)和Stream using块时关闭。运行VS的代码分析时,这会导致CA2202警告。
直接从CA2202页获得的另一种解决方案是使用try / finally块。正确设置,这将只关闭一次连接。
Microsoft建议在CA2202底部附近使用以下内容:
Stream stream = null;
try
{
stream = new FileStream("file.txt", FileMode.OpenOrCreate);
using (StreamWriter writer = new StreamWriter(stream))
{
stream = null;
// Use the writer object...
}
}
finally
{
if(stream != null)
stream.Dispose();
}
代替...
// Generates a CA2202 warning
using (Stream stream = new FileStream("file.txt", FileMode.Open))
using (XmlReader reader = new XmlReader (stream))
{
// Use the reader object...
}
解决此问题的一种简单方法是重写StreamWriter类的Dispose方法。有关如何执行此代码的信息,请参见此处:
通过“使用”关键字或显式调用处置的流