using statement - ensure the correct use of disposable objects
The using
statement ensures the correct use of an IDisposable instance:
var numbers = new List<int>();
using (StreamReader reader = File.OpenText("numbers.txt"))
{
string line;
while ((line = reader.ReadLine()) is not null)
{
if (int.TryParse(line, out int number))
{
numbers.Add(number);
}
}
}
When the control leaves the block of the using
statement, an acquired IDisposable instance is disposed. In particular, the using
statement ensures that a disposable instance is disposed even if an exception occurs within the block of the using
statement. In the preceding example, an opened file is closed after all lines are processed.
Use the await using
statement to correctly use an IAsyncDisposable instance:
await using (var resource = new AsyncDisposableExample())
{
// Use the resource
}
For more information about using of IAsyncDisposable instances, see the Using async disposable section of the Implement a DisposeAsync method article.
You can also use a using
declaration that doesn't require braces:
static IEnumerable<int> LoadNumbers(string filePath)
{
using StreamReader reader = File.OpenText(filePath);
var numbers = new List<int>();
string line;
while ((line = reader.ReadLine()) is not null)
{
if (int.TryParse(line, out int number))
{
numbers.Add(number);
}
}
return numbers;
}
When declared in a using
declaration, a local variable is disposed at the end of the scope in which it's declared. In the preceding example, disposal happens at the end of a method.
A variable declared by the using
statement or declaration is readonly. You cannot reassign it or pass it as a ref
or out
parameter.
You can declare several instances of the same type in one using
statement, as the following example shows:
using (StreamReader numbersFile = File.OpenText("numbers.txt"), wordsFile = File.OpenText("words.txt"))
{
// Process both files
}
When you declare several instances in one using
statement, they are disposed in reverse order of declaration.
You can also use the using
statement and declaration with an instance of a ref struct that fits the disposable pattern. That is, it has an instance Dispose
method, which is accessible, parameterless and has a void
return type.
The using
statement can also be of the following form:
using (expression)
{
// ...
}
where expression
produces a disposable instance. The following example demonstrates that:
StreamReader reader = File.OpenText(filePath);
using (reader)
{
// Process file content
}
Warning
In the preceding example, after control leaves the using
statement, a disposable instance remains in scope while it's already disposed. If you use that instance further, you might encounter an exception, for example, ObjectDisposedException. That's why we recommend declaring a disposable variable within the using
statement or with the using
declaration.
C# language specification
For more information, see The using statement section of the C# language specification and the proposal note about "pattern-based using" and "using declarations".