Cleaning up after yourself (Dispose(void) doesn't get called for you)

Despite my large and growing number of Dispose-related blogs, I really don't like writing about Dispose. Or rather, I don't like that Dispose is in such a confusing state that it requires so much reading material. :) But here we are again. I'd like to start posting some of the common Dispose questions I get, in hopes that it will save time for others.

I got an email asking why StreamWriter's data isn't getting flushed to disk. In their scenario, the problem manifested as a partial file; i.e., the final block wasn't flushed to disk. But they also showed a smaller repro in which no data is flushed to disk.

using System;
using System.IO;
using System.Threading;

public class StreamWriterWrapper : IDisposable {
    public StreamWriter writer;

    public static void Main(string[] args) {
        StreamWriterWrapper test = new StreamWriterWrapper(@"C:\temp\test.txt");
        test.writer.WriteLine("some text");
        test.writer.WriteLine("some more text");
    }

    public StreamWriterWrapper(string filename) {
        writer = new StreamWriter(filename);
    }

    public void Dispose() {
        writer.Close();
    }
}

The user's comment was: it looks like .NET isn't calling Dispose for us, even though we implemented IDisposable and provided a Dispose method, and this is why the data isn't getting flushed.

The user is completely right. And this is a key difference between Dispose and finalization. Dispose(void) doesn't get called for you; your code needs to explicitly call it.  This is different than finalization, and since Brian has already written up a great description of this difference, I'll refer you to his blog for more details:

https://blogs.msdn.com/bclteam/archive/2007/10/30/dispose-pattern-and-object-lifetime-brian-grunkemeyer.aspx

Comments