Why do we need the finalizer in the disposable pattern if it is not guaranteed that it will be called by the garbage collector?

96 views Asked by At

My question is: in C#, why do we need the finalizer in the disposable pattern if it is not guaranteed that it will be called by the garbage collector?

I have problems understanding the philosophy behind C# finalizers. My main confusion arises when I read textbook examples of how the Disposable pattern should be implemented. See, for example, this tutorial from Microsoft. Consider this example, where I have a simple disposable class that creates a file, writes "Hello world" there, and upon disposal, "frees unmanaged resources" - deletes the file. If I intentionally forget to dispose the object then in this example, the finalizer is not called, and eventually, the file is not deleted.

public class FileWriter : IDisposable
{
    private string filePath = "D:\\test\\unmanaged.txt";
    private bool _disposedValue;

    public FileWriter()
    {
        File.WriteAllText(filePath, "hello world");
    }

    ~FileWriter()
    {
        Dispose(false);
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!_disposedValue)
        {
            if (disposing)
            {
                // dispose managed state (managed objects)
            }

            // disposing unmanaged resources
            File.Delete(filePath);
            _disposedValue = true;
        }
    }
}

class Program
{
    static void Main()
    {
        // We intentionally don't use "using" here, so we don't dispose of the object 
        // explicitly. In this case, the finalizer is not called, and the 
        // corresponding file is not deleted.
        var myFileWriter = new FileWriter();
    }
}

So, why do we need the finalizer in the disposable pattern if it is not guaranteed to be called?

1

There are 1 answers

0
Jon Skeet On

If I intentionally forget to dispose the object then in this example, the finalizer is not called, and eventually, the file is not deleted.

Only because your app terminates immediately. Finalization isn't guaranteed on app termination - it's best effort. On my machine, the finalizer is called. It probably depends on how you're running your code.

Most of the time, finalizers will execute (eventually) because the application keeps running for long enough. You shouldn't rely on finalizers, but they're a useful backstop.