Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does IAsyncDisposable Have a Reference Implementation?

With IDisposable, I often used an abstract base class because implementing it was so difficult. Mostly because you can use the interface to dispose both managed and unmanaged references and each is disposed differently.

public abstract class Disposable : IDisposable
{
    ~Disposable() => this.Dispose(false);

    public bool IsDisposed { get; private set; }

    public void Dispose()
    {
        this.Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void DisposeManaged() {}
    protected virtual void DisposeUnmanaged() {}

    protected void ThrowIfDisposed()
    {
        if (this.IsDisposed)
        {
            throw new ObjectDisposedException(this.GetType().Name);
        }
    }

    private void Dispose(bool disposing)
    {
        if (!this.IsDisposed)
        {
            if (disposing)
            {
                this.DisposeManaged();
            }

            this.DisposeUnmanaged();
            this.IsDisposed = true;
        }
    }
}

With IAsyncDisposable, I can't find a reference implementation. Also, I believe it only handles managed resources mainly because it's so new and there are no unmanaged resources that require async to be disposed. Is this correct? If so, is the implementation then trivial?

like image 951
Muhammad Rehan Saeed Avatar asked Sep 26 '19 08:09

Muhammad Rehan Saeed


People also ask

Why is IAsyncDisposable?

You should use IAsyncDisposable only when you have a class that needs to release resources asynchronously. In other words, you should use IAsyncDisposable if your class (or any of its subclasses) allocates resources that also implement IAsyncDisposable.

What is DisposeAsync?

The DisposeAsync() method The public parameterless DisposeAsync() method is called implicitly in an await using statement, and its purpose is to free unmanaged resources, perform general cleanup, and to indicate that the finalizer, if one is present, need not run.


1 Answers

The pattern that we decided on for the framework, and will publish in Framework Design Guidelines, 3rd Edition is:

public async ValueTask DisposeAsync()
{
    await DisposeAsyncCore().ConfigureAwait(false);
    Dispose(false);
    GC.SuppressFinalize(this);
}

protected virtual ValueTask DisposeAsyncCore()
{
    // Code goes here that is the async equivalent to Dispose(true)
}

That does, of course, imply that all IAsyncDisposable types are also IDisposable. Also, sealed types can skip DisposeAsyncCore().

like image 149
bartonjs Avatar answered Oct 01 '22 10:10

bartonjs