On this code:
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;
}
}
...I get, courtesy of Visual Studio's Code Analysis tool, the warning, "Do not dispose objects multiple times...To avoid generating a System.ObjectDisposedException you should not call Dispose more than one time on an object" on the "fStream.Close();" line.
Why? Is fStream disposed in the line above, where the BinaryReader is closed?
Wouldn't I be better off refactoring it like this anyway:
. . .
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();
. . .
?
Code Analysis is right; Code Analysis is wrong.
Yes, you're closing the FileStream twice. This is harmless. So is disposing it twice. Multiple disposal happens. It is the responsibility of the developer of a disposable component to handle multiple disposal properly and without throwing exceptions1.
However, while calling
Dispose()
on a disposedFileStream
is a no-op by convention, the same isn't true of your code, which callsClose()
on a disposed stream. Don't do that.Your suggested fix with the nested using is fine.
1 The contract for
IDisposable.Dispose
requires:The formal term for this behavior is idempotence.
BinaryReader.Close
also closes the underlying stream, so this would indeed cause the stream to be disposed of twice. But that's not a real problem, disposing twice doesn't hurt.You could write this much better as
This is the bomb-proof version:
leaveOpen
argument on theBinaryReader
constructor ensures that disposing (closing) it won't also close the stream