C#
exception-handling
using-statement
try-finally
.NET

'using' statement vs 'try finally'

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In C#, the using statement and a try/finally block solve the same core problem: cleanup that must happen even when exceptions occur. For IDisposable resources, using is usually the better choice because it is clearer and compiles down to the try/finally pattern you would otherwise write by hand.

using Is Structured Disposal

A classic using block looks like this:

csharp
1using (var stream = File.OpenRead("data.txt"))
2{
3    // use stream
4}

The compiler expands that into logic equivalent to:

csharp
1var stream = File.OpenRead("data.txt");
2try
3{
4    // use stream
5}
6finally
7{
8    if (stream != null)
9    {
10        stream.Dispose();
11    }
12}

That is why people call using syntactic sugar. It is not weaker than try/finally. It is a more focused expression of the same guarantee for disposable resources.

Why using Is Usually Better

For IDisposable objects, using has practical advantages:

  • less boilerplate
  • clearer resource lifetime
  • fewer chances to forget disposal

This matters most when the resource is a file handle, database connection, network stream, or any unmanaged wrapper that should be released promptly.

try/finally Is More General

try/finally is still important because cleanup is not always about Dispose(). Sometimes you need to:

  • release a lock
  • restore state
  • stop a timer
  • undo temporary settings

Example:

csharp
1bool oldValue = SomeGlobalFlag.Enabled;
2SomeGlobalFlag.Enabled = true;
3
4try
5{
6    RunOperation();
7}
8finally
9{
10    SomeGlobalFlag.Enabled = oldValue;
11}

This is not a disposal scenario, so using is not the right tool.

Modern C# Also Has Using Declarations

Current C# adds an even shorter form:

csharp
1using var stream = File.OpenRead("data.txt");
2using var reader = new StreamReader(stream);
3
4string content = reader.ReadToEnd();
5Console.WriteLine(content);

The disposal still happens automatically at the end of the containing scope. This often reads better than nested using blocks.

Disposal Order Matters

When you use multiple disposable resources, they are disposed in reverse order of creation. That is important when one resource depends on another:

csharp
1using var stream = File.OpenRead("data.txt");
2using var reader = new StreamReader(stream);
3
4Console.WriteLine(reader.ReadLine());

Here reader is disposed before stream, which is exactly what you want.

When try/finally Still Wins

Even for disposable resources, you may still choose try/finally when cleanup has extra conditions or more complex control flow:

csharp
1var connection = OpenConnection();
2bool shouldDispose = true;
3
4try
5{
6    UseConnection(connection);
7}
8finally
9{
10    if (shouldDispose)
11    {
12        connection.Dispose();
13    }
14}

This is rarer, but it shows that try/finally remains the underlying general-purpose primitive.

Async Disposal Follows the Same Idea

In modern .NET, asynchronous cleanup extends the same pattern through await using for IAsyncDisposable resources:

csharp
await using var stream = new SomeAsyncDisposableResource();
await stream.FlushAsync();

The idea is unchanged: express the lifetime of the resource as clearly as possible and let the language generate the right cleanup structure for you.

Common Pitfalls

  • Thinking using is somehow less safe than try/finally.
  • Forgetting that using only applies cleanly to IDisposable-style cleanup.
  • Writing manual try/finally disposal code everywhere and increasing boilerplate for no benefit.
  • Not understanding disposal order when several resources depend on one another.
  • Using using for a scope that is too wide and keeping expensive resources open longer than necessary.

Summary

  • 'using is the preferred C# syntax for disposing IDisposable resources.'
  • It compiles to the same cleanup guarantee you would write with try/finally.
  • 'try/finally is still the right tool for non-disposal cleanup or special control flow.'
  • Modern C# using declarations make resource lifetime even clearer in many cases.
  • Choose the construct that matches the cleanup problem rather than forcing everything into one style.
  • Prefer the clearest lifetime expression.

Course illustration
Course illustration

All Rights Reserved.