Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

A using declaration is a variable declaration preceded by the using keyword that instructs the compiler to automatically dispose of the object at the end of the enclosing lexical scope. Introduced in C# 8.0, it provides a syntactic alternative to the traditional using statement block, reducing indentation while ensuring deterministic resource cleanup.

Technical Requirements

To utilize a synchronous using declaration, the declared type must be implicitly convertible to the System.IDisposable interface. For ref struct types, the compiler supports pattern-based synchronous disposal, requiring only an accessible public void Dispose() method. As of C# 13, ref struct types can also implement interfaces directly, meaning they can explicitly implement IDisposable as well. For asynchronous disposal (await using), the type must be implicitly convertible to the System.IAsyncDisposable interface, or it must satisfy the asynchronous disposable pattern. The pattern requires an accessible DisposeAsync method that returns a ValueTask or another awaitable type. This pattern-based approach is utilized by types like the ConfiguredAsyncDisposable struct returned by ConfigureAwait(false). Once declared, a using variable is implicitly read-only; the compiler prevents reassignment or modification of the reference.

Syntax and Compiler Translation

Using Declaration Syntax:
{
    using var resource = new DisposableResource();
    // Operations utilizing 'resource'
    
} // Disposal is implicitly invoked here
At compile time, the Roslyn compiler lowers the using declaration into a standard try...finally block. For types implicitly convertible to IDisposable, the compiler casts the instance to IDisposable before invoking Dispose(). When dealing with normal value types (structs), boxing is avoided during this interface call because the compiler emits the constrained. IL prefix before the virtual method call. For types utilizing pattern-based disposal, the compiler emits a direct method call instead of an interface cast. Equivalent Lowered Syntax:
// Conceptual pseudo-code representing compiler lowering logic.
// Note: For non-nullable value types, the compiler omits the null check 
// at the IL level, as 'resource != null' would be invalid in actual C#.
{
    var resource = new DisposableResource();
    try
    {
        // Operations utilizing 'resource'
    }
    finally
    {
        if (resource != null)
        {
            ((IDisposable)resource).Dispose();
        }
    }
}

Scope and Disposal Order

The lifetime of the object is strictly bound to the lexical scope in which the using declaration appears. Disposal occurs immediately when execution exits that scope, whether via normal control flow, a return statement, or an unhandled exception. When multiple using declarations exist within the same scope, the compiler guarantees that the objects are disposed in reverse order of their declaration (Last-In, First-Out, or LIFO).
{
    using var resource1 = new DisposableResource();
    using var resource2 = new DisposableResource();
    
} // resource2 is disposed, followed by resource1

Asynchronous Disposal

For types implicitly convertible to IAsyncDisposable or those satisfying the asynchronous disposable pattern, the await modifier is prepended to the declaration. The compiler lowers this into an asynchronous try...finally block, invoking DisposeAsync() and awaiting the returned awaitable.
{
    await using var asyncResource = new AsyncDisposableResource();
    // Asynchronous operations
    
} // await asyncResource.DisposeAsync() is implicitly called here

Out Variables and Pattern Matching

A using declaration cannot be used directly within an out variable declaration or a pattern matching declaration. The variable must be explicitly declared as a standalone statement to establish its scope and lifetime boundaries clearly for the compiler.
Master C# with Deep Grasping Methodology!Learn More