Courses/C#/IDisposable & Resource Management
    Back to Course

    Lesson 25: IDisposable, Finalizers & Resource Management

    Learn to manage unmanaged resources correctly — implement IDisposable, use using statements, and avoid resource leaks.

    What You'll Learn

    • • The full IDisposable pattern with finalizer safety net
    • • using statements and C# 8 using declarations
    • • IAsyncDisposable for async resource cleanup
    • • SafeHandle and wrapping unmanaged resources

    🧠 Real-World Analogy

    The GC is like automatic housekeeping that cleans up .NET objects. But some things — like hotel room keys, rental cars, or library books — need to be returned explicitly. IDisposable is your "return the keys" contract. The using statement ensures you never forget.

    The Dispose Pattern

    Whenever your class holds unmanaged resources (file handles, database connections, network sockets), implement IDisposable. The pattern includes a protected virtual Dispose(bool) method and a finalizer as a safety net. Always call GC.SuppressFinalize(this) in Dispose to skip the finalizer when cleanup was done properly.

    IDisposable & using Statement

    Implement the full dispose pattern and see automatic cleanup with using.

    Try it Yourself »
    C#
    using System;
    using System.IO;
    
    // The Dispose Pattern — proper implementation
    class DatabaseConnection : IDisposable
    {
        private bool _disposed = false;
        private string _connectionString;
        
        public DatabaseConnection(string connectionString)
        {
            _connectionString = connectionString;
            Console.WriteLine($"Connection opened: {_connectionString}");
        }
        
        public void ExecuteQuery(string sql)
        {
            ObjectDisposedException.ThrowIf(_disposed, this);
            
    ...

    IAsyncDisposable

    When cleanup involves I/O operations (flushing streams, closing network connections), use IAsyncDisposable with await using. This avoids blocking threads during disposal.

    IAsyncDisposable & await using

    Implement async resource cleanup for I/O-bound disposal.

    Try it Yourself »
    C#
    using System;
    using System.IO;
    using System.Threading.Tasks;
    
    // IAsyncDisposable for async cleanup
    class AsyncResource : IAsyncDisposable, IDisposable
    {
        private Stream? _stream;
        private bool _disposed = false;
        
        public AsyncResource(string path)
        {
            _stream = new MemoryStream();
            Console.WriteLine($"Async resource created for: {path}");
        }
        
        public async Task WriteAsync(string data)
        {
            ObjectDisposedException.ThrowIf(_disposed, this);
           
    ...

    SafeHandle & Stacking using Declarations

    For wrapping native OS handles, prefer SafeHandle subclasses over raw IntPtr — they provide guaranteed cleanup even if exceptions occur. C# 8+ using declarations let you stack multiple disposables cleanly.

    SafeHandle & Stacked using

    Wrap unmanaged resources safely and dispose multiple resources in order.

    Try it Yourself »
    C#
    using System;
    using System.Runtime.InteropServices;
    using Microsoft.Win32.SafeHandles;
    
    // SafeHandle for wrapping unmanaged resources
    class UnmanagedBuffer : IDisposable
    {
        private SafeBuffer? _buffer;
        private bool _disposed = false;
        private readonly int _size;
        
        public UnmanagedBuffer(int sizeInBytes)
        {
            _size = sizeInBytes;
            // In real code, this would wrap a native handle
            Console.WriteLine($"Allocated {sizeInBytes} bytes of unmanaged memory");
        
    ...

    Pro Tip

    In .NET 7+, use ObjectDisposedException.ThrowIf(disposed, this) instead of manually throwing. It's cleaner and generates better error messages.

    Common Mistakes

    • • Not implementing IDisposable when holding file/network handles — causes resource leaks
    • • Forgetting GC.SuppressFinalize(this) — finalizer runs unnecessarily
    • • Accessing disposed objects — always check and throw ObjectDisposedException

    Lesson Complete!

    You now know how to properly manage resources in C#. Next, apply design patterns like Factory, Strategy, and Observer to build maintainable architectures.

    Sign up for free to track which lessons you've completed and get learning reminders.

    Previous

    Cookie & Privacy Settings

    We use cookies to improve your experience, analyze traffic, and show personalized ads. You can manage your preferences below.

    By clicking "Accept All", you consent to our use of cookies for analytics and personalized advertising. You can customize your preferences or reject non-essential cookies.

    Privacy PolicyTerms of Service