关于此代码:
public static string Base64FromFileName(string fileName)
{
try
{
FileInfo fInfo = new FileInfo(fileName);
long numBytes = fInfo.Length;
FileStream fStream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fStream);
byte[] bdata = br.ReadBytes((int)numBytes);
br.Close();
fStream.Close();
return Convert.ToBase64String(bdata);
}
catch(Exception e)
{
throw e;
}
}
...我得到了,Visual Studio的代码分析工具,警告," 不要多次丢弃对象...为了避免生成System.ObjectDisposedException,你不应该调用在对象上多次处理"在" fStream.Close();"线。
为什么呢? fStream是否在上面的行中,BinaryReader被关闭了?
无论如何我最好不要像这样重构它:
. . .
using (FileStream fStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
using (BinaryReader br = new BinaryReader(fStream))
{
byte[] bdata = br.ReadBytes((int)numBytes);
} //br.Close();
} //fStream.Close();
. . .
答案 0 :(得分:5)
BinaryReader.Close
也会关闭基础流,因此这确实会导致流被处理两次。但这不是一个真正的问题,处理两次并不会造成伤害。
你可以写得更好
using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
using (var br = new BinaryReader(fs, new UTF8Encoding(), true))
{
return Convert.ToBase64String(br.ReadBytes((int)numBytes));
}
这是防弹版:
leaveOpen
构造函数上的布尔BinaryReader
参数确保处置(关闭)它也不会关闭流答案 1 :(得分:3)
代码分析是对的;代码分析是错误的。
是的,你关闭了两次FileStream。这是无害的。所以要两次处理它。多次处理发生。一次性部件的开发人员有责任正确处理多次处理,并且不会抛出异常 1 。
但是,按照约定,在已处置的Dispose()
上调用FileStream
是无操作的,对您的代码来说,同样的情况也是如此,它会在处置时调用Close()
流。别这么做。
使用嵌套使用的建议修复很好。
1 The contract for IDisposable.Dispose
要求:
如果多次调用对象的
Dispose
方法,则该对象必须忽略第一个之后的所有调用。如果多次调用Dispose
方法,则该对象不得抛出异常。 <{1}}以外的实例方法可以在资源已经处理时抛出Dispose
。
此行为的正式用语是 idempotence 。