Search code examples
c#dispose

How to dispose File.OpenRead()


How to I dispose the File.OpenRead() correctly. I am currently using the below code?

using (BinaryReader br = new BinaryReader(File.OpenRead(path)))
{
   myByte = br.ReadByte();
}

I get the following in Visual Studio when analyzing the code:

Warning 1 CA2000 : Microsoft.Reliability : In method 'Program.Main(string[])', object 'File.OpenRead(path)' is not disposed along all exception paths. Call System.IDisposable.Dispose on object 'File.OpenRead(path)' before all references to it are out of scope.


Solution

  • At first glance, this looks like a false positive, because disposing the BinaryReader will also dispose the FileStream returned by File.OpenRead:

    From: http://msdn.microsoft.com/en-us/library/azy2k2bx.aspx

    When the disposing parameter is true, this method releases all resources held by any managed objects that this BinaryReader references. This method invokes the Dispose method of each referenced object.

    However, there is one corner case, where the FileStream is really not disposed: When the constructor of BinaryReader throws an exception!

    Solution:
    The correct way to write your code would be like this:

    using (var fs = File.OpenRead(path))
    {
        BinaryReader br = new BinaryReader(fs);
        myByte = br.ReadByte();
    }
    

    Background:
    BinaryReader only holds a reference to the FileStream and therefore doesn't need to be disposed.
    Code Analysis shares this opinion.


    BTW: When using this solution for a writable stream, it is important to flush the writer before the stream is disposed:

    using (var fileStream = new FileStream(...))
    {
        var writer = new StreamWriter(fileStream);
    
        writer.WriteLine(...);
    
        writer.Flush(); // <-- Important
    }
    

    If you forget this, your stream might not contain everything that has been written using the StreamWriter.