Some objects hold resources the garbage collector does not manage: open files, network sockets, database connections, operating system handles. They implement IDisposable, and you release the resource by calling Dispose(). The using statement calls it for you at a fixed point, even if an exception is thrown.
This page is about the using statement. The using System; lines at the top of a file are a different feature, the using directive, which imports a namespace.
A using block
using (declaration) { body } creates the object, runs the body, then calls Dispose. A small class that prints from Dispose shows exactly when that happens:
Output:
open db
db sends SELECT 1
close db
open api
api sends GET /orders
close api
error handled
The second block throws, and "close api" still prints, before the catch handles the exception. That guarantee is the reason to use using instead of calling Dispose() on the last line yourself: a manual call is skipped by any exception thrown before it.
What using compiles to
The compiler expands a using block into a try/finally. These two are equivalent:
using (var writer = new StreamWriter("log.txt"))
{
writer.WriteLine("started");
}
// is compiled as:
{
var writer = new StreamWriter("log.txt");
try
{
writer.WriteLine("started");
}
finally
{
if (writer != null) ((IDisposable)writer).Dispose();
}
}
Three details follow from the expansion. The variable is scoped to the block and read-only inside it (you cannot reassign writer). The object must implement IDisposable, or the code does not compile. And a null value is allowed: Dispose is simply skipped, which is handy when a factory might return nothing.
Files and streams
File and stream classes are the everyday case. A StreamWriter buffers text in memory, and Dispose flushes the buffer to disk and closes the file handle:
Output:
id,total
1001,59.90
1002,12.50
Without Dispose, the writer's last lines may still be sitting in its buffer, and on Windows the open handle keeps other programs (and your own next File.Delete) from touching the file. Helpers such as File.WriteAllText and File.ReadAllLines open and dispose internally, so they need no using. See files for more.
Several resources: disposal order
Stack using statements without braces between them to open several resources in one block. They are disposed in reverse order of creation:
Output:
acquire file
acquire buffer
acquire writer
working
release writer
release buffer
release file
acquire a
acquire b
both open
release b
release a
Reverse order is what layered resources need: a writer wraps a buffer that wraps a file, so the writer must flush into the buffer before the buffer writes to the file, before the file closes.
The using declaration (C# 8)
C# 8 added a form with no braces. The variable is disposed when the enclosing scope ends, usually the end of the method:
static void ExportReport(string path, IEnumerable<string> rows)
{
using var writer = new StreamWriter(path);
writer.WriteLine("Report");
foreach (string row in rows)
{
writer.WriteLine(row);
}
} // writer.Dispose() runs here, at the end of the method
It removes a level of indentation, which adds up when a method uses two or three resources. The disposal order rule is the same: declarations in one scope are disposed in reverse order. The trade-off is that the resource stays open until the scope ends, so when a file should be closed before the method does more work, keep the block form or put the declaration in its own { } block.
For objects whose cleanup is asynchronous (IAsyncDisposable, such as many database connections and streams), C# 8 also has await using, which awaits DisposeAsync() in the same place.
Implementing IDisposable in your own class
Implement IDisposable when your class owns something disposable (it created a stream, a timer, a connection) and so must dispose it in turn. For the common case, that is a short method:
Output:
1. user ana logged in
2. order 1001 created
AuditLog disposed
Caught ObjectDisposedException
The rules this follows: Dispose disposes everything the object owns; calling it more than once does nothing the second time; and using the object after disposal throws ObjectDisposedException. using (log) also shows that the block can take an existing variable instead of a declaration.
The longer "dispose pattern" with a protected virtual void Dispose(bool disposing) method and a finalizer is only needed when a class directly holds an unmanaged handle (a raw pointer from native code). In modern .NET, wrap such handles in a SafeHandle subclass instead, and the simple version above is all your class needs.
Common mistakes
- Returning an object created in a
usingblock. It is disposed when the block exits, so the caller receives a closed stream. Return the data, or let the caller own theusing. - Forgetting
usingon streams and writers. Buffered data can be lost and files stay locked. - Disposing a shared object. Dispose only what you own. A long-lived
HttpClient, for example, is meant to be shared and reused, not created and disposed per request. - Using an object after the block. Methods on a disposed object throw
ObjectDisposedException. - Relying on the garbage collector. It frees memory, not files or sockets, and never calls
Dispose.
Frequently Asked Questions
What does the using statement do in C#?
using (var x = ...) { ... } calls x.Dispose() when the block ends, whether it ends normally, through return, or because an exception was thrown. The compiler turns it into a try/finally with the Dispose call in the finally, so the resource is released at a known point instead of whenever the garbage collector runs.
What is IDisposable in C#?
IDisposable is an interface with one method, void Dispose(). A class implements it when it holds something that must be released explicitly: a file handle, a network socket, a database connection, a timer. Any object whose type implements IDisposable should be disposed when you are done with it, usually with using.
What is the difference between using and using var?
using (var x = ...) { } disposes at the end of its block. The using declaration using var x = ...; (C# 8 and later) has no block of its own: it disposes when the enclosing scope ends, typically the end of the method. It saves nesting when a resource should live for the rest of the method.
In what order are multiple using objects disposed?
In reverse order of creation. With using (var a = ...) using (var b = ...) { }, b is disposed first and then a. That is the order you want when b depends on a, such as a StreamWriter wrapping a FileStream.
Does the garbage collector call Dispose?
No. The garbage collector frees memory, and it may run a finalizer at some unpredictable later time, but it never calls Dispose. A file left undisposed can stay locked, and its buffered data may never be written. That is why using exists.