The IDisposable interface has always been an important cornerstone to correctly cleaning up resources when you no longer needed them. Together with the using statement it became an easy pattern to implement and use in C#.
Unfortunately you couldn’t use the IDisposable when you had some async work to do to cleanup your resources. This is solved with the introduction of the IAsyncDisposable interface in C# 8.
Be aware that when you implement the IAsyncDisposable interface, and your class is not sealed you should not only implement the interface but also provide a second method DisposeAsyncCore with the following signature:
protected virtual ValueTask DisposeAsyncCore() | |
{ | |
} |
This is to help guarantee that all resources are cleaned up correctly when your class is used as a base class.
public class ExampleAsyncDisposable : IAsyncDisposable, IDisposable | |
{ | |
public void Dispose() | |
{ | |
Dispose(disposing: true); | |
GC.SuppressFinalize(this); | |
} | |
public async ValueTask DisposeAsync() | |
{ | |
await DisposeAsyncCore(); | |
Dispose(disposing: false); | |
GC.SuppressFinalize(this); | |
} | |
protected virtual void Dispose(bool disposing) | |
{ | |
if (disposing) | |
{ | |
//Cleanup your resources | |
} | |
} | |
protected virtual async ValueTask DisposeAsyncCore() | |
{ | |
//Cleanup your resources async | |
} | |
} |
Your code can than be used in an ‘await using’:
await using (var exampleAsyncDisposable = new ExampleAsyncDisposable()) | |
{ | |
} |
More information: Implementing a dispose async method