Warm tip: This article is reproduced from stackoverflow.com, please click
c# c#-8.0 iasyncenumerable iasyncdisposable

How to safely dispose of IAsyncDisposable objects retrieved with await foreach?

发布于 2020-03-28 23:14:49

Can I do this using using var:

await foreach (var response in _container.GetItemQueryStreamIterator(query))
{
   using var safeResponse = response;
   //use the safeResponse
}

or should I do this:

await foreach (var response in _container.GetItemQueryStreamIterator(query))
{ 
  try {
    //use response
  } finally {
    response?.Dispose();
  }
}

or can I just go without disposing because the iterator is an IAsyncDisposable and the await foreach will do it for me?

await foreach (var response in _container.GetItemQueryStreamIterator(query))
{
   //use the response
}
Questioner
fred_
Viewed
30
Orace 2020-01-31 18:29

Given an IEnumerable<IDisposable> (with or without Async in it), there is no rules on who should dispose the elements. And therefor, (and hopefully) enumerating it will not dispose it's element.

Disposing the elements is your responsibility.

In your question you want to dispose them will iterating, so option 3 is not possible, you have to dispose them by yourself.

Option 1 and 2 are equivalent but both are smelly.

You may write:

await foreach (var item in enumerable)
{
  await using (item)
  {
    ..          
  }
}

// by playing with your autoformatter
await foreach (var item in enumerable) await using (item)
{
  ..
}

Sadly I didn't see any better solution. And it looks like you have to be careful if you work with ValueType. Maybe we should ask for something like this:

await foreach(await using var e in c)

Edit of course somebody already ask for it.