Знание того, какое исключение ожидает, если оно есть, во время финализатора - хорошая возможность. VB.net делает это возможным, хотя и неловко. C # нет. В vb.net методика такая:
Dim PendingException as Exception = Nothing
Try
.. Do Whatever
PendingException = Nothing ' Important -- See text
Catch Ex As Exception When CopyFirstArgumentToSecondAndReturnFalse(Ex, PendingException)
Throw ' Should never happen if above function returns false like it should
Finally
' PendingException will be Nothing if Try completed normally, or hold exception if not.
Try
.. Cleanup
Catch Ex as Exception
Throw New FailedCleanupException(Ex, PendingException)
End Try
End Try
Обратите внимание, что это может быть очень полезным методом, если гарантируется, что код, который будет вызван исключением, в конечном итоге либо сгенерирует исключение, либо сгенерирует новое статистическое исключение. Среди прочего, если исключение будет в конечном итоге необработанным, ловушка отладчика «Необработанное исключение» будет срабатывать при возникновении исходного исключения, а не при последнем его вызове. Это может значительно облегчить отладку, так как для отладчика будет доступно много состояния программы, которое в противном случае было бы сброшено.
Обратите внимание, что PendingException явно очищается в конце основного блока Try. PendingException может иметь значение, даже если нет ожидающих исключений. Это может произойти, если что-то в блоке Try с двойным вложением выдает исключение, которое не будет перехвачено в нашем блоке try, а предложение finally внутреннего блока Try выдает исключение, которое перехватывается в блоке Try с одиночным вложением. В этом случае исходное исключение фактически исчезает. Возможно, будет полезно сгенерировать специальную запись в журнале, если либо «CopyFirstParameterToSecondAndReturnFalse», либо «PendingException = Nothing» выполняется, когда PendingException не равно NULL, поскольку этот сценарий, вероятно, будет представлять собой ошибку, которую нельзя регистрировать где-либо еще, но если есть несколько вложенных блоков catch, они могут генерировать избыточные записи журнала.
Учитывая, что C # не поддерживает фильтрацию исключений, необходимую для этого подхода, может быть полезно написать оболочку VB, которая может вызывать делегаты C #, но обеспечивает необходимую логику обработки исключений.
EDIT
Невозможно выполнить возврат в блоке try-catch, но я не вижу, чтобы это вызывало проблему с чем-то вроде:
{
Exception ex = null;
try
{
CaptureExceptionInfoButDontCatch(ex,{
/* Stuff that might throw */
});
yield return whatever;
CaptureExceptionInfoButDontCatch(ex,{
/* More that might throw */
});
}
finally
{
/* If ex is nothing, exception occurred */
}
}