2013-03-17 2 views
0

Лучший способ объяснить мой вопрос находится в следующем псевдокоде:Как перейти от одного обработчика исключений к другому?

try 
{ 
    //Do work 
} 
catch (SqlException ex) 
{ 
    if (ex.Number == -2) 
    { 
     debugLogSQLTimeout(ex); 
    } 
    else 
    { 
     //How to go to 'Exception' handler? 
    } 
} 
catch (Exception ex) 
{ 
    debugLogGeneralException(ex); 
} 
+0

почему не вы просто debugLogGeneralException (ex); вместо вашего комментария? –

+0

@romanm: Как я уже сказал, это всего лишь псевдокод, и это не реальная функция в моем фактическом примере. – c00000fd

+1

все, о чем я говорю, вы должны поставить логику «Исключительный обработчик» вместо своего комментария, а не «туда» –

ответ

3
Exception ex = null; 
try 
{ 
    //Do work 
} 
catch (SqlException sqlEx) 
{ 
    ex = sqlEx; 
    if (ex.Number == -2) 
    { 
     //.. 
    } 
    else 
    { 
     //.. 
    } 
} 
catch (Exception generalEx) 
{ 
    ex = generalEx; 
} 
finally() 
{ 
    if (ex != null) debugLogGeneralException(ex); 
} 
+0

+1! Я думал так же ! –

+0

Очень приятно. Я надеялся на команду 'rethrow', но это тоже сработает. – c00000fd

1

Первый catch пункт, который соответствует единственный, который может возможно работать на том же try блоке.

Лучший способ, которым я могу думать, чтобы делать то, что вы пытаетесь это включить слепки и условные в более общем виде:

try 
{ 
    //Do work 
} 
catch (Exception ex) 
{ 
    var sqlEx = ex as SqlException; 
    if (sqlEx != null && sqlEx.Number == -2) 
    { 
     debugLogSQLTimeout(ex); 
    } 
    else 
    { 
     debugLogGeneralException(ex); 
    } 
} 

Если вы нашли себя пишешь это снова и снова на протяжении ваших данных слоя, по крайней мере, потребуется время, чтобы инкапсулировать его в методе.

+0

Очень приятно. Я не знал, что можно сделать подобное исключение. Это не приведет к исключению его собственной, не так ли? (Скажем, если это исключение арифметического переполнения.) – c00000fd

+0

В этом случае, учитывая, что мы сравниваем sqlEx.Number с постоянным значением (которое я, вероятно, объявлял бы 'const' для производственного кода), я не подумайте, что существует реальная опасность появления необработанного исключения. –

+0

Хм ... ТЕПЕРЬ Я понимаю ваш вопрос ... Думаю. И нет, процесс 'as'-casting исключения из другого типа НЕ будет каким-то образом инициировать повторное поднятие этого исключения. Вам придется «бросить»(), чтобы это произошло. –

0

Я не верю, что есть какой-либо способ сделать это, поскольку блоки catch находятся в разных областях. Невозможно повторно бросить, не выходя из блока try, и никак не «вызвать» последний блок catch, потому что он срабатывает только во время исключения.

Я бы предложил то же самое, что и roman m above, и просто сделать тот же звонок. В противном случае вам нужно сделать что-то действительно плохое. Как нижний сумасшедший код, который вы никогда не должны использовать, но я включил его, потому что он делает что-то вроде того, что вы хотите.

В целом, я думаю, что вы делаете контроль над нормальным потоком через исключения, которые не рекомендуется. Если вы пытаетесь отслеживать таймауты, вы, вероятно, должны просто обращаться с этим другим способом.

Обратите внимание, что вы можете сделать что-то вроде кода ниже с безумием оператора goto, но я включил его, чтобы никто не мог забыть, что это за плохая идея. =)

void Main() 
{ 
    Madness(new NotImplementedException("1")); //our 'special' case we handle 
    Madness(new NotImplementedException("2")); //our 'special' case we don't handle 
    Madness(new Exception("2")); //some other error 
} 

void Madness(Exception e){ 
    Exception myGlobalError; 

    try 
    { 
     throw e; 
    } 
    catch (NotImplementedException ex) 
    { 
     if (ex.Message.Equals("1")) 
     { 
      Console.WriteLine("handle special error"); 
     } 
     else 
     { 
      myGlobalError = ex; 
      Console.WriteLine("going to our crazy handler"); 
      goto badidea; 
     } 
    } 
    catch (Exception ex) 
    { 
     myGlobalError = ex; 
     Console.WriteLine("going to our crazy handler"); 
     goto badidea; 
    } 
    return; 

    badidea: 
    try{ 
     throw myGlobalError; 
    } 
    catch (Exception ex) 
    { 
     Console.WriteLine("this is crazy!"); 
    } 
} 
// Define other methods and classes here 
+0

Да, вы правы, это сумасшедшая идея)) – c00000fd

+0

=) Я надеялся удостовериться, что это было достаточно сумасшедшим, и никто на самом деле его не использовал. Я согласен с комментарием roman m на исходный код. Независимо от того, что вы делаете, вы все равно будете делать что-то такое безумное. Даже try/catch /, наконец, заставит вас иметь нулевую проверку независимо от ошибки на каждой отдельной операции, которая вызывает try/catch/finally. вероятно, не слишком много накладных расходов, но это что-то. ни один из ответов не дает «перейти» к другому обработчику исключений, потому что вы не можете. –