Menu
Coddy logo textTech

Using vs. Try-Finally

Part of the Logic & Flow section of Coddy's C# journey — lesson 28 of 66.

Both using statements and try-finally blocks help manage resources that need to be properly disposed of. The using statement provides a cleaner, more concise way to ensure that IDisposable objects are properly cleaned up.

Let's look at a try-finally approach first. Here, StreamReader is a class that reads text from a file — it holds an open file handle, which is a resource that must be released when we're done:

StreamReader reader = null;
try
{
    reader = new StreamReader("file.txt");
    string content = reader.ReadToEnd();
    Console.WriteLine(content);
}
finally
{
    if (reader != null)
    {
        reader.Dispose();
    }
}

The finally block guarantees that Dispose() is called to release the file handle, even if an exception occurs inside the try block.

The using statement simplifies this pattern. It declares and initializes the resource in parentheses, and automatically calls Dispose() when the block exits — whether normally or due to an exception:

using (StreamReader reader = new StreamReader("file.txt"))
{
    string content = reader.ReadToEnd();
    Console.WriteLine(content);
}

This is equivalent to the try-finally example above, but with less boilerplate code.

The using statement automatically calls Dispose() when the block exits, even if an exception occurs. It replaces the try-finally cleanup pattern — not try-catch. If you also need to handle exceptions, you can still wrap a using block inside a try-catch.

challenge icon

Challenge

Easy

Create a method named processFile that:

  1. Takes a filename as a string parameter
  2. Uses the using statement with a StreamReader to read all lines from the file
  3. Returns the number of lines in the file
  4. If a FileNotFoundException occurs, print "File not found" and return -1

Cheat sheet

The using statement provides automatic resource cleanup for IDisposable objects, ensuring Dispose() is called even if exceptions occur. It replaces the verbose try-finally pattern.

Try-finally approach:

StreamReader reader = null;
try
{
    reader = new StreamReader("file.txt");
    string content = reader.ReadToEnd();
    Console.WriteLine(content);
}
finally
{
    if (reader != null)
    {
        reader.Dispose();
    }
}

Using statement (cleaner approach):

using (StreamReader reader = new StreamReader("file.txt"))
{
    string content = reader.ReadToEnd();
    Console.WriteLine(content);
}

Both approaches ensure Dispose() is called when the block exits. The using statement handles this automatically, removing the need for a manual null check and finally block.

Key points:
using replaces try-finally — not try-catch
try-catch can still be combined with using to handle exceptions
StreamReader reads text files and implements IDisposable, making it ideal for use with using

Try it yourself

using System;
using System.IO;

class ProcessFile
{
    public static int processFile(string filename)
    {
        // Write your code here
    }
}
quiz iconTest yourself

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

All lessons in Logic & Flow