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

1

6

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
}
Spears answered 31/1, 2020 at 9:40 Comment(2)
Related: What is the difference between using and await using? And how can I decide which one to use?Gallopade
@TheodorZoulias thank you very interestingSpears
C
4

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.

Clingfish answered 31/1, 2020 at 10:7 Comment(1)
Thank you will be using your auto formatted suggestion :)Spears

© 2022 - 2024 — McMap. All rights reserved.