A using statement manages an IDisposable resource whose lifetime should end with a scope. It ensures Dispose runs when execution leaves that scope, including when an exception interrupts the work. section 4.1.4
Garbage collection eventually reclaims memory, but it does not provide a predictable time for releasing nonmemory resources such as file handles. IDisposable and Dispose provide the cleanup contract that using applies. section 4.1.4
Use the resource-management form of using as follows:
- Use a using block when several operations share an explicitly visible scope. section 4.1.4
- Use a single using statement when disposal should occur at the end of the enclosing code block. section 4.1.4
- Apply it only to types that implement IDisposable; the shorthand calls Dispose automatically. section 4.1.4
- Decide ownership deliberately when a method receives a stream; leaving it open can let the caller continue using it. section 4.2.1
Reading and disposing a JSON stream
static void FindWithJsonDom(Stream inStream, Stream outStream, string category) { using var writer = new StreamWriter(outStream, Encoding.UTF8, leaveOpen: true); using var jsonDoc = JsonDocument.Parse(inStream); foreach (var jokeElement in jsonDoc.RootElement.EnumerateArray()) { // Find matching elements and write results. } } section 4.2.1
Listing 4.12 Call Dispose even in the case of an exception
var reader = file.OpenText();
try
{
while ((line = reader.ReadLine()) != null); #1
}
finally
{
reader?.Dispose();
}
Compare explicit try/finally cleanup with the equivalent using form, including disposal when reading fails. section 4.1.4
The keyword using also has namespace-related meanings, including global and static using statements. Those forms reduce imports or qualify fewer names; they do not perform resource disposal. section 2.5
