5
votes

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.

4

4 Answers

17
votes

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.

3
votes

Hows about:

using (Filestream fs = File.OpenRead(Path))
{
    using (BinaryReader br = new BinaryReader(fs))
    {
        myByte = br.ReadByte();
    }
}
0
votes

File.OpenRead returns a FileStream, which is also IDisposible. You can put it in an outer using block if you like, or declare it and dispose it outside your current using.

0
votes

Both the FileStream that's created by File.OpenRead and the BinaryReader that you create on that FileStream need to be disposed of, so you need an explicit reference to each:

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