Было бы (ИМХО очень) полезно, если бы существовал вариант IDisposable
, метод Dispose
которого принял параметр, указывающий, какое исключение, если таковое вообще было, ожидало, когда оно было запущено.Среди прочего, в случае, если Dispose
не может выполнить ожидаемую очистку, он сможет генерировать исключение, которое включает информацию о более раннем исключении.Это также позволило бы методу Dispose
генерировать исключение, если код «забывает» делать то, что он должен был делать в блоке using
, но не перезаписывать любое другое исключение, которое может привести к преждевременному завершению работы блока using.К сожалению, пока такой функции не существует.
Существует множество статей, в которых предлагаются способы использования функций API для выяснения, существует ли ожидающее исключение.Одна из основных проблем с такими подходами состоит в том, что возможно, что код может выполняться в блоке finally
для try
, который успешно завершился, но он может быть вложен в блок finally
, чей try
завершился преждевременно.Даже если бы метод Dispose
мог бы идентифицировать, что такая ситуация существовала, у него не было бы способа узнать, к какому блоку try
он «принадлежал».Можно сформулировать примеры, где применима любая из этих ситуаций.
Как таковой, наилучшим подходом, вероятно, является наличие явного метода «успеха» и принятие отказа, если он не вызван, и представление о том, что последствия забывания вызоваМетод «успеха» должен быть очевиден, даже если не было выброшено исключение.Одна вещь, которая может быть полезна в качестве простого служебного метода, может быть похожа на
T Success<T>(T returnValue)
{
Success();
return T;
}
, что позволяет использовать код вроде:
return scopeGuard.Success(thingThatMightThrow());
вместо
var result = thingThatMightThrow();
scopeGuard.Success();
return result;