Menu
Coddy logo textTech

IDisposable & using Statement

Part of the Object Oriented Programming section of Coddy's C# journey — lesson 45 of 70.

Some objects hold onto resources that the garbage collector can't automatically clean up - file handles, database connections, network sockets. The IDisposable interface provides a standard way to release these resources when you're done with them.

A class implements IDisposable by providing a Dispose() method:

public class FileHandler : IDisposable
{
    private bool disposed = false;
    
    public void Dispose()
    {
        if (!disposed)
        {
            Console.WriteLine("Releasing resources...");
            disposed = true;
        }
    }
}

You could call Dispose() manually, but what if an exception occurs before you reach that line? The using statement guarantees cleanup happens, even when things go wrong:

using (FileHandler handler = new FileHandler())
{
    // Work with the handler
}  // Dispose() called automatically here

Modern C# offers a cleaner syntax with the using declaration, which disposes the object when it goes out of scope:

void ProcessFile()
{
    using FileHandler handler = new FileHandler();
    // Work with handler
}  // Dispose() called when method exits

The using statement works with any type that implements IDisposable. Built-in classes like StreamReader, SqlConnection, and HttpClient all implement this interface, making proper resource management straightforward and reliable.

challenge icon

Challenge

Easy

Let's build a database connection simulator that demonstrates proper resource management using the IDisposable interface and the using statement. You'll create a class that tracks when connections are opened and closed, ensuring resources are always properly released.

You'll organize your code across two files:

  • DatabaseConnection.cs: Create a DatabaseConnection class in the DataAccess namespace that implements IDisposable. Your connection should:
    • Have a ConnectionName property (string, read-only) set through the constructor
    • Track whether the connection has been disposed using a private boolean field
    • Print Connection opened: {ConnectionName} when the object is created (in the constructor)
    • Implement the Dispose() method to print Connection closed: {ConnectionName} - but only if not already disposed (prevent double-disposal)
    • Have a Query(string sql) method that returns Executing on {ConnectionName}: {sql}
  • Program.cs: In your main file, demonstrate proper resource management by using the using statement with your database connection. Create a connection, execute a query, and let the using block handle cleanup automatically.

You will receive two inputs:

  • The connection name (e.g., MainDB)
  • The SQL query to execute (e.g., SELECT * FROM Users)

Use a using statement to create your connection. Inside the block, call the Query method and print its result. When the using block ends, Dispose() will be called automatically.

For example, if the inputs are MainDB and SELECT * FROM Users, the output should be:

Connection opened: MainDB
Executing on MainDB: SELECT * FROM Users
Connection closed: MainDB

Notice how the connection is automatically closed when the using block ends - you never have to remember to call Dispose() manually. This pattern ensures resources are always cleaned up, even if an exception occurs inside the block!

Cheat sheet

The IDisposable interface provides a standard way to release resources that the garbage collector can't automatically clean up (file handles, database connections, network sockets).

A class implements IDisposable by providing a Dispose() method:

public class FileHandler : IDisposable
{
    private bool disposed = false;
    
    public void Dispose()
    {
        if (!disposed)
        {
            Console.WriteLine("Releasing resources...");
            disposed = true;
        }
    }
}

The using statement guarantees cleanup happens automatically, even when exceptions occur:

using (FileHandler handler = new FileHandler())
{
    // Work with the handler
}  // Dispose() called automatically here

Modern C# offers a cleaner syntax with the using declaration:

void ProcessFile()
{
    using FileHandler handler = new FileHandler();
    // Work with handler
}  // Dispose() called when method exits

The using statement works with any type that implements IDisposable, including built-in classes like StreamReader, SqlConnection, and HttpClient.

Try it yourself

using System;
using DataAccess;

class Program
{
    public static void Main(string[] args)
    {
        string connectionName = Console.ReadLine();
        string sqlQuery = Console.ReadLine();
        
        // TODO: Use a 'using' statement to create a DatabaseConnection
        // Inside the using block:
        // 1. Call the Query method with the sqlQuery
        // 2. Print the result of the Query method
        // The Dispose method will be called automatically when the using block ends
        
    }
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming