-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Description
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) statementcorresponds 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.