Как безопасно утилизировать объекты IAsyncDisposable, полученные с помощью await foreach? - PullRequest
6 голосов
/ 31 января 2020

Могу ли я сделать это, используя using var:

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

, или я должен сделать это:

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

или я могу просто go без утилизации, потому что итератор IAsyncDisposable и await foreach сделает это за меня?

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

1 Ответ

4 голосов
/ 31 января 2020

Учитывая IEnumerable<IDisposable> (с или без Async в нем), нет никаких правил относительно того, кто должен располагать элементами. И поэтому (и, мы надеемся), перечисление его не приведет к уничтожению его элемента.

Утилизация элементов - ваша ответственность.

В вашем вопросе вы хотите, чтобы они были удалены, итерация, поэтому вариант 3 не возможно, вы должны избавиться от них самостоятельно.

Варианты 1 и 2 эквивалентны, но оба вонючие.

Вы можете написать:

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

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

К сожалению, я не сделал не вижу лучшего решения. И похоже, что вы должны быть осторожны, если работаете с ValueType. Может быть, мы должны попросить что-то вроде этого:

await foreach(await using var e in c)

Редактировать конечно кто-то уже попросил об этом .

...