В языках с try-catch-finally возможно ли каким-либо образом выполнить действие для всех обработчиков исключений?

#language-agnostic #try-catch-finally

#не зависит от языка #try-catch-finally

Вопрос:

Существует ли какой-либо язык, который поддерживает что-то вроде приведенной ниже конструкции, или есть хороший способ добиться этого с помощью повсеместного try-catch-finally?

 try
{

} catch(Exception1 e)
  { .... }
  catch(Exception2 e)
  { .... }
  catch-finally
   {
      //Perform action, such as logging
   }
  finally
   {
     //This always occurs but I only want to log when an exception occurs.
   }
  

Я понимаю, что это зависит от конкретного языка, но есть ли какая-либо подобная поддержка в Java, C #, C , PHP и т.д.?

Ответ №1:

Поместите «глобальную» попытку / catch в вашу основную программу или высокоуровневый метод. Это улавливает все исключения, которые не перехвачены в другом месте.

 try
{
     // Main method, or higher level method call
} 
catch (Exception ex)
{
     // Log exception here
}
  

Затем в ваших подчиненных предложениях try / catch просто обработайте свои исключения обычным способом, а затем повторно создайте.Повторно созданное исключение всплывет на ваш основной try / catch и будет зарегистрировано.

 try
{
     // Do your thing
}
catch(SomeException ex)
{
     // Handle exception here

     // rethrow exception to logging handler 
     throw;
}
  

Ответ №2:

Я так не думаю, поскольку поведение, которое вы описываете, можно легко смоделировать как:

 boolean success = false;

try {
  ...
  success = true;
} catch (Exception_1 e) {
  ...
}
...
} catch (Exception_N e) {
  ...
} finally {
  if (success) {
    // your "finally"
  } else {
    // your "catch-finally"
  }
}
  

Ответ №3:

Вы можете легко выполнить это на C #. Простым способом было бы сохранить исключение в ваших блоках catch, а затем в вашем блоке finally войти, если объект exception не равен null.

 Exception ex;

try
{

}
catch (ExceptionType1 type1)
{
    ex = type1;
}
catch (ExceptionType2 type2)
{
    ex = type2;
}
finally
{
    if (ex != null)
    {
        //Log
    }
}
  

Ответ №4:

В Visual Basic есть конструкция, которая может быть использована для этого. На самом деле это не «finally» в смысле [почти] никогда не завершающегося сбоем выполнения, но это будет поддерживать случай, когда вы хотите регистрировать только те исключения, которые вы обрабатываете, и у вас есть доступ к объекту exception в общем коде. У вас также есть гибкость, заключающаяся в том, что общий код выполняется до или после кода отдельного типа исключения.

 Try
    ...
Catch ex As Exception When TypeOf(ex) Is Type1 OrElse TypeOf(ex) Is Type2
    ...
    If TypeOf(ex) Is Type1 Then
        ...
    ElseIf TypeOf(ex) Is Type2 Then
        ...
    End If
End Try
  

Ответ №5:

Что-то вроде этого, при условии, что в языке нет throw параметров для повторного заполнения пойманного исключения:

 try
{

} catch(Everything) {
    try {
        throw;
    } catch (Exception1 e) {
        ....
    } catch (Exception2 e) {
        ....
    } finally {
        //Perform action, such as logging
    }
} finally {
        //This always occurs but I only want to log when an exception occurs.
}
  

Это если вы хотите регистрировать всякий раз, когда возникает исключение — если вы хотите регистрировать только те, которые вы на самом деле перехватываете, тогда не помещайте «Выполнить действие» в блок finally, просто поместите его после окончания внутреннего try-catch.