Skip to content

IAsyncDisposable, using statements, and async/await #114

@sharwell

Description

@sharwell

With the introduction of support for await inside of a finally block, I'd like to propose the following extension to the using statement in C#.

The System.IAsyncDisposable interface

public interface IAsyncDisposable : IDisposable
{
  Task DisposeAsync();
}

Modification to the using statement

When a using statement appears inside of an async method, the translation of the using statement is modified to the following.

A using statement of the form

using (ResourceType resource = expression) statement

corresponds to one of four possible expansions. When ResourceType is a non-nullable value type which implements System.IAsyncDisposable, the expansion is

{
    ResourceType resource = expression;
    try {
        statement;
    }
    finally {
        await ((IAsyncDisposable)resource).DisposeAsync();
    }
}

Otherwise, when ResourceType is a non-nullable value type which does not implement System.IAsyncDisposable, the expansion is

{
    ResourceType resource = expression;
    try {
        statement;
    }
    finally {
        ((IDisposable)resource).Dispose();
    }
}

Otherwise, when ResourceType is a nullable value type or a reference type other than dynamic, the expansion is:

{
    ResourceType resource = expression;
    try {
        statement;
    }
    finally {
        if (resource != null) {
            IAsyncDisposable tmp = resource as IAsyncDisposable;
            if (tmp != null) {
                await tmp.DisposeAsync();
            }
            else {
                ((IDisposable)resource).Dispose();
            }
        }
    }
}

Otherwise, when ResourceType is dynamic, the expansion is

{
    ResourceType resource = expression;
    IDisposable d = (IDisposable)resource;
    try {
        statement;
    }
    finally {
        if (d != null) {
            IAsyncDisposable tmp = d as IAsyncDisposable;
            if (tmp != null) {
                await tmp.DisposeAsync();
            }
            else {
                d.Dispose();
            }
        }
    }
}

The IAsyncDisposable interface has no impact on the expansion of using statements which appear in any context other than a method marked with the async modifier.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions