question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

IAsyncDisposable, using statements, and async/await

See original GitHub issue

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.

Issue Analytics

  • State:closed
  • Created 9 years ago
  • Reactions:41
  • Comments:77 (34 by maintainers)

github_iconTop GitHub Comments

28reactions
ljw1004commented, Jan 28, 2015

I find it scary that there’ll be an implicit “await” in your code (i.e. re-entrancy vulnerability) with no indication of it in your code. Could you tell me your thoughts on a compound keyword?

async using (var x = <expr>)
{
   ...
}
17reactions
davkeancommented, May 24, 2018

@mlehmk That only works if Dispose has no observable behavior.

Pretend you implement that logic in FileStream that you’ve opened for exclusive access to a file, that you want to delete that immediately afterwards after disposing the FileStream. How would you know when you can delete the file?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Implement a DisposeAsync method
IAsyncDisposable interface was introduced as part of C# 8.0. ... DisposeAsync() method is called implicitly in an await using statement, ...
Read more >
How to properly use IAsyncDisposable in C#8
How to implement IAsyncDisposable ... The interface requires an implementation of a method with the signature public ValueTask DisposeAsync().
Read more >
c# - How to deal with async "using" statement pitfall?
One easy way to avoid this is to start relying on IAsyncDisposable and await using , which cannot be confused with using block...
Read more >
C# Async/Await Interview Questions And Answers (2023)
To use a class implementing IAsyncDisposable , you can use the await using statement, which ensures that resources are released in an ...
Read more >
The IAsyncDisposable interface in .NET Core 3.0
Overall, I think the IAsyncDisposable interface and the await keyword for the using statement is a meaningful extension. It rounds off the async...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found