Search code examples
c#visual-studio-2013filestreamdisposebinaryreader

Why does Code Analysis tell me, "Do not dispose objects multiple times" here:


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();
. . .

?


Solution

  • 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

    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));
    }
    

    This is the bomb-proof version:

    • Anything that is successfully constructed is guaranteed to be disposed
    • You won't dispose of the stream twice because the boolean leaveOpen argument on the BinaryReader constructor ensures that disposing (closing) it won't also close the stream