{"action":"created","issue":{"url":"https://api.github.com/repos/dotnet/roslyn/issues/114","labels_url":"https://api.github.com/repos/dotnet/roslyn/issues/114/labels{/name}","comments_url":"https://api.github.com/repos/dotnet/roslyn/issues/114/comments","events_url":"https://api.github.com/repos/dotnet/roslyn/issues/114/events","html_url":"https://github.com/dotnet/roslyn/issues/114","id":55791167,"number":114,"title":"IAsyncDisposable, using statements, and async/await","user":{"login":"sharwell","id":1408396,"avatar_url":"https://avatars.githubusercontent.com/u/1408396?v=3","gravatar_id":"","url":"https://api.github.com/users/sharwell","html_url":"https://github.com/sharwell","followers_url":"https://api.github.com/users/sharwell/followers","following_url":"https://api.github.com/users/sharwell/following{/other_user}","gists_url":"https://api.github.com/users/sharwell/gists{/gist_id}","starred_url":"https://api.github.com/users/sharwell/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sharwell/subscriptions","organizations_url":"https://api.github.com/users/sharwell/orgs","repos_url":"https://api.github.com/users/sharwell/repos","events_url":"https://api.github.com/users/sharwell/events{/privacy}","received_events_url":"https://api.github.com/users/sharwell/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/dotnet/roslyn/labels/Area-Language%20Design","name":"Area-Language Design","color":"5319e7"},{"url":"https://api.github.com/repos/dotnet/roslyn/labels/Feature%20Request","name":"Feature Request","color":"fc2929"},{"url":"https://api.github.com/repos/dotnet/roslyn/labels/Feature%20Specification","name":"Feature Specification","color":"fc2929"},{"url":"https://api.github.com/repos/dotnet/roslyn/labels/Language-C%23","name":"Language-C#","color":"207de5"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":29,"created_at":"2015-01-28T17:55:35Z","updated_at":"2015-11-13T16:31:25Z","closed_at":null,"body":"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#.\r\n\r\n### The `System.IAsyncDisposable` interface\r\n\r\n```csharp\r\npublic interface IAsyncDisposable : IDisposable\r\n{\r\n  Task DisposeAsync();\r\n}\r\n```\r\n\r\n### Modification to the `using` statement\r\n\r\nWhen a `using` statement appears inside of an `async` method, the translation of the `using` statement is modified to the following.\r\n\r\nA `using` statement of the form\r\n\r\n```csharp\r\nusing (ResourceType resource = expression) statement\r\n```\r\n\r\ncorresponds to one of four possible expansions. When `ResourceType` is a non-nullable value type which implements `System.IAsyncDisposable`, the expansion is\r\n\r\n```csharp\r\n{\r\n    ResourceType resource = expression;\r\n    try {\r\n        statement;\r\n    }\r\n    finally {\r\n        await ((IAsyncDisposable)resource).DisposeAsync();\r\n    }\r\n}\r\n```\r\n\r\nOtherwise, when `ResourceType` is a non-nullable value type which does not implement `System.IAsyncDisposable`, the expansion is\r\n\r\n```csharp\r\n{\r\n    ResourceType resource = expression;\r\n    try {\r\n        statement;\r\n    }\r\n    finally {\r\n        ((IDisposable)resource).Dispose();\r\n    }\r\n}\r\n```\r\n\r\nOtherwise, when `ResourceType` is a nullable value type or a reference type other than `dynamic`, the expansion is:\r\n\r\n```csharp\r\n{\r\n    ResourceType resource = expression;\r\n    try {\r\n        statement;\r\n    }\r\n    finally {\r\n        if (resource != null) {\r\n            IAsyncDisposable tmp = resource as IAsyncDisposable;\r\n            if (tmp != null) {\r\n                await tmp.DisposeAsync();\r\n            }\r\n            else {\r\n                ((IDisposable)resource).Dispose();\r\n            }\r\n        }\r\n    }\r\n}\r\n```\r\n\r\nOtherwise, when `ResourceType` is `dynamic`, the expansion is\r\n\r\n```csharp\r\n{\r\n    ResourceType resource = expression;\r\n    IDisposable d = (IDisposable)resource;\r\n    try {\r\n        statement;\r\n    }\r\n    finally {\r\n        if (d != null) {\r\n            IAsyncDisposable tmp = d as IAsyncDisposable;\r\n            if (tmp != null) {\r\n                await tmp.DisposeAsync();\r\n            }\r\n            else {\r\n                d.Dispose();\r\n            }\r\n        }\r\n    }\r\n}\r\n```\r\n\r\nThe `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."},"comment":{"url":"https://api.github.com/repos/dotnet/roslyn/issues/comments/156480641","html_url":"https://github.com/dotnet/roslyn/issues/114#issuecomment-156480641","issue_url":"https://api.github.com/repos/dotnet/roslyn/issues/114","id":156480641,"user":{"login":"alrz","id":3105979,"avatar_url":"https://avatars.githubusercontent.com/u/3105979?v=3","gravatar_id":"","url":"https://api.github.com/users/alrz","html_url":"https://github.com/alrz","followers_url":"https://api.github.com/users/alrz/followers","following_url":"https://api.github.com/users/alrz/following{/other_user}","gists_url":"https://api.github.com/users/alrz/gists{/gist_id}","starred_url":"https://api.github.com/users/alrz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alrz/subscriptions","organizations_url":"https://api.github.com/users/alrz/orgs","repos_url":"https://api.github.com/users/alrz/repos","events_url":"https://api.github.com/users/alrz/events{/privacy}","received_events_url":"https://api.github.com/users/alrz/received_events","type":"User","site_admin":false},"created_at":"2015-11-13T16:31:25Z","updated_at":"2015-11-13T16:31:25Z","body":"Since there is a `Task` involving, I think it wouldn't be a good idea to ignore it. It should return to the caller (awaiter) and then you can decide on `ConfigureAwait`, etc.\r\n\r\nMaybe\r\n```cs\r\nTask task = using(var res = new AsyncDisposable(cancellationToken)) { }\r\n```\r\nand of course you can `await` it right away\r\n```cs\r\nawait using(var res = new AsyncDisposable(cancellationToken)) { }\r\n```\r\nBut, this can be done with a simple extension method\r\n```cs\r\nstatic async Task UsingAsync<T>(this T disposable, Action<T> action)\r\n    where T : IAsyncDisposable\r\n{\r\n    try { action(disposable); }\r\n    finally { await disposable.DisposeAsync(); }\r\n}\r\n\r\nstatic async Task<TResult> UsingAsync<T, TResult>(this T disposable, Func<T, TResult> func)\r\n    where T : IAsyncDisposable\r\n{\r\n    try { return func(disposable); }\r\n    finally { await disposable.DisposeAsync(); }\r\n}\r\n``` "}}