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 hereModern 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 exitsThe 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
EasyLet'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 aDatabaseConnectionclass in theDataAccessnamespace that implementsIDisposable. Your connection should:- Have a
ConnectionNameproperty (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 printConnection closed: {ConnectionName}- but only if not already disposed (prevent double-disposal) - Have a
Query(string sql)method that returnsExecuting on {ConnectionName}: {sql}
- Have a
Program.cs: In your main file, demonstrate proper resource management by using theusingstatement with your database connection. Create a connection, execute a query, and let theusingblock 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: MainDBNotice 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 hereModern C# offers a cleaner syntax with the using declaration:
void ProcessFile()
{
using FileHandler handler = new FileHandler();
// Work with handler
} // Dispose() called when method exitsThe 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
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesNamespaces & DirectivesIntro to Classes & ObjectsThe 'this' KeywordMethods and ParametersFields vs PropertiesConstructorsObject InitializersRecap - Simple Calculator4Inheritance
Basic Inheritance (:) SyntaxThe 'base' KeywordVirtual & Override KeywordsSealed ClassesThe 'object' Base ClassRecap - Employee Hierarchy7Advanced Features
Operator OverloadingIndexers (this[])ToString() OverrideExtension MethodsRecap - Custom List2Properties & Static Members
Auto-Implemented PropertiesRead/Write-Only PropertiesStatic Fields & MethodsStatic ClassesExpression-Bodied Members5Polymorphism & Interfaces
Compile vs Runtime PolyInterface vs Abstract ClassMultiple InterfacesExplicit InterfacesUpcasting & DowncastingRecap - Shape Calculator8Advanced OOP Concepts
Composition over InheritanceGenerics (Classes & Methods)Delegates and EventsAttributes and ReflectionIDisposable & using StatementDependency Injection Basics