Difference Between Dispose() and Finalize() in C#

In C#, both Dispose() and Finalize() are used to release unmanaged resources such as file handles, database connections, or network sockets. These are resources not handled by the .NET runtime's garbage collector.

Learn more about unmanaged resources on the official Microsoft documentation.

๐Ÿงน What is Dispose()?

  • Part of the IDisposable interface
  • Must be called manually or via a using block
  • Releases resources deterministically
  • Ideal for: Files, database connections, network streams

๐Ÿ—‘️ What is Finalize()?

  • Special method: ~ClassName() (destructor syntax)
  • Called automatically by the Garbage Collector
  • Executes non-deterministically
  • Used as a backup if Dispose() is not called
  • Warning: Finalize can slow down garbage collection


๐Ÿ“Š Key Differences: Dispose() vs Finalize()

Feature Dispose() Finalize()
Triggered by Developer (manual) Garbage Collector (automatic)
Defined in IDisposable interface Destructor syntax (~ClassName())
Execution timing Deterministic Non-deterministic
Role Primary cleanup mechanism Backup mechanism
Performance impact Efficient Slower due to GC overhead
Accessibility Public Protected

๐Ÿงช Real Example: Using Dispose() and Finalize() Together

FileWriter class demonstrating proper disposal:
public class FileWriter : IDisposable
{
    private StreamWriter _writer;
    private bool _disposed = false;

    public FileWriter(string path)
    {
        _writer = new StreamWriter(path);
    }

    public void Write(string text)
    {
        if (_disposed)
            throw new ObjectDisposedException("FileWriter");

        _writer.WriteLine(text);
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this); // Prevent Finalize from running
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                _writer?.Dispose(); // Managed resources
            }

            // Unmanaged cleanup if needed
            _disposed = true;
        }
    }

    ~FileWriter()
    {
        Dispose(false);
    }
}

✔️ Usage Example:

using (var file = new FileWriter("log.txt"))
{
    file.Write("Logging message...");
}
// Dispose is called automatically at the end of the using block

๐Ÿšซ Common Mistakes to Avoid

  • Forgetting to call Dispose() or not using a using block
  • Not suppressing finalization with GC.SuppressFinalize after disposing
  • Not implementing Dispose(bool disposing) pattern when using finalizers

๐Ÿ“ Summary & Best Practices

  • Use Dispose() for controlled, manual cleanup of unmanaged resources.
  • Use Finalize() only when absolutely necessary, and always pair it with the Dispose(bool) pattern.
  • Best Practice: Prefer using blocks with IDisposable objects to ensure timely cleanup.
  • Design Tip: Always call GC.SuppressFinalize to prevent redundant cleanup.
  • For async cleanup, consider implementing IAsyncDisposable.

Comments

Popular posts from this blog

Debouncing & Throttling in RxJS: Optimizing API Calls and User Interactions

Promises in Angular

Comprehensive Guide to C# and .NET Core OOP Concepts and Language Features