title: What's the recommended way to deal with leaked IAsyncDisposable instances?
body: <p>I've been familiarizing myself with some of the things (that are planned to be) added in C# 8 &amp; .NET Core 3.0, and am unsure on the correct way to implement <a href="https://docs.microsoft.com/en-us/dotnet/api/system.iasyncdisposable?view=netstandard-2.1" rel="noreferrer">IAsyncDisposable</a> (at time of writing,  this link has literally no guidance).</p>
  
  <p>In particular, it is unclear to me what to do in the case when an instance isn't explicitly disposed - that is, it isn't wrapped in an <code>async using(...)</code> and <code>.DisposeAsync()</code> isn't explicitly called.</p>
  
  <p>My first thought was to do that same thing I'd do when implementing <a href="https://docs.microsoft.com/en-us/dotnet/api/system.idisposable?view=netframework-4.7.2" rel="noreferrer">IDisposable</a>:</p>
  
  <ul>
  <li>My <code>DisposeAsync()</code> implementation calls a <code>DisposeAsync(bool disposing)</code> with <code>disposing: true</code></li>
  <li>Implement a finalizer (with <code>~MyType()</code>) that calls <code>DisposeAsync(disposing: false)</code></li>
  <li><code>DisposeAsync(bool disposing)</code> actually frees and/or disposes everything, and suppresses finalizing if <code>disposing == true</code>.</li>
  </ul>
  
  <p>My concerns are that there's nothing to await the results of <code>DisposeAsync(bool)</code> in the finalizer, and explicitly waiting in a finalizer seems really really dangerous.</p>
  
  <p>Of course "just leak" also seems less than ideal.</p>
  
  <p>To make this concrete, here's a (simplified) example class that <em>does</em> have a finalizer:</p>
  
  <pre><code>internal sealed class TestAsyncReader: IAsyncDisposable
  {
      private bool IsDisposed =&gt; Inner == null;
      private TextReader Inner;
      internal TestAsyncReader(TextReader inner)
      {
          Inner = inner;
      }
  
      // the question is, should this exist?
      ~TestAsyncReader()
      {
          DisposeAsync(disposing: false);
      }
  
      private ValueTask DisposeAsync(bool disposing)
      {
          // double dispose is legal, but try and do nothing anyway
          if (IsDisposed)
          {
              return default;
          }
  
          // should a finalizer even exist?
          if (disposing)
          {
              GC.SuppressFinalize(this);
          }
  
          // in real code some resources explicitly implement IAsyncDisposable,
          //   but for illustration purposes this code has an interface test
          if (Inner is IAsyncDisposable supportsAsync)
          {
              var ret = supportsAsync.DisposeAsync();
              Inner = null;
              return ret;
          }
  
          // dispose synchronously, which is uninteresting
          Inner.Dispose();
          Inner = null;
          return default;
      }
  
      public ValueTask DisposeAsync()
      =&gt; DisposeAsync(disposing: true);
  }
  </code></pre>
  
  <p>So, is there any guidance around proper handling of leaked <code>IAsyncDisposable</code> instances?</p>