2010-10-27 2 views
17

Questo è un po 'astratto, ma esiste un modo per lanciare un'eccezione e inserirla in più blocchi catch? Ad esempio, se corrisponde a un'eccezione specifica seguita da un'eccezione non specifica.Posso eseguire più blocchi Catch?

catch(Arithmetic exception) 
{ 
    //do stuff 
} 
catch(Exception exception) 
{ 
    //do stuff 
} 

risposta

30

È perfettamente accettabile disporre di più blocchi di cattura di tipi diversi. Tuttavia, il comportamento è che il primo blocco candidato gestisce l'eccezione.

Non inserirà ENTRAMBI i blocchi di cattura. Il primo blocco catch che corrisponde al tipo di eccezione gestirà quell'eccezione specifica e nessun'altra, anche se è stata riscritta nel gestore. Tutti quelli successivi verranno saltati quando un'eccezione entra in un blocco catch.

Al fine di avere un'eccezione catturati in entrambi i blocchi, si avrebbe bisogno di entrambi i blocchi nido in questo modo:

try 
{ 
    try 
    { 
     // Do something that throws ArithmeticException 
    } 
    catch(ArithmeticException arithException) 
    { 
     // This handles the thrown exception.... 

     throw; // Rethrow so the outer handler sees it too 
    } 
} 
catch (Exception e) 
{ 
    // This gets hit as well, now, since the "inner" block rethrew the exception 
} 

In alternativa, è possibile filtrare in un gestore di eccezioni generica in base al tipo specifico di eccezione.

+2

L'annidamento funziona correttamente per gerarchie semplici a un livello, ma può essere brutto se si dispone di codice condiviso che deve essere eseguito per diversi casi di eccezione. Questo non è un disaccordo con l'approccio, ma un'osservazione che non è sempre appropriato. – tvanfosson

+0

@tvanfosson: Sì, ecco perché ho anche aggiunto l'opzione di filtro. Anche la tua opzione è molto carina. –

18

No. Non è possibile eseguire il codice in entrambi i blocchi di cattura per una singola eccezione.

Probabilmente rifatterò il codice nel blocco di eccezioni generico in qualcosa che può essere chiamato da entrambi.

try 
{ 
    // blah blah blah 
{ 
catch(Arithmetic ae) 
{ 
    HandleArithmeticException(ae); 
    HandleGenericException(ae); 
} 
catch(Exception e) 
{ 
    HandleGenericException(e); 
} 
1

Non è possibile avere più di un blocco di eccezioni per gestire la stessa eccezione. Ma che cosa si può fare è catturare l'eccezione generale, quindi tentare di lanciare al più specifico, in questo modo:

catch (Exception exception) 
{ 
    var aex = exception as ArithmeticException 
    if (aex != null) 
    { 
     // do stuff specific to this exception type 
    } 
    // then do general stuff 
} 
0

Questo è noto come il filtraggio eccezione e non è supportato in C# (mi hanno detto è possibile in VB.NET).

Una soluzione potrebbe essere quella di intercettare l'eccezione generale e quindi controllare il tipo di eccezione nel blocco catch e eseguire qualsiasi elaborazione specifica prima di proseguire con il resto del blocco.

1

Come altri hanno affermato che l'eccezione verrà catturata dal blocco di cattura più specifico.

Ciò porta a una mia frustrazione seppure con una gestione delle eccezioni. Vorrei che tu potessi fare qualcosa di simile

catch (ArgumentNullExcpetion, ArugmentOutOfRangeException ex) 
{ 

} 

Invece di dover fare

catch (ArgumentNullExcpetion e) 
{ 
} 
catch (ArugmentOutOfRangeException outOfRange) 
{ 
} 

Capisco il ragionamento contro questo che, probabilmente, si fanno le cose diverse per le diverse eccezioni, ma a volte mi desidera combinarli.

+1

Non entrambi derivano da ArgumentException - se vuoi davvero fare la stessa cosa per entrambi, prendi ArgumentException. Se si desidera rilevare solo le eccezioni secondarie, è necessario filtrare (e ripetere) ArgumentException utilizzando la logica condizionale. Il tuo punto generale è buono, ma questo non è il miglior esempio. Forse qualcosa come ValidationException (errore del modello) e SqlException (violazione del vincolo) dove non si trovano nella stessa gerarchia è un esempio migliore. – tvanfosson

+1

Non penso proprio al 100% quando dici "l'eccezione sarà catturata dal blocco di cattura più specifico" Questo dipende anche dall'ordine. Quindi, se hai un problema tutto in primo luogo, tutto ciò ricadrà sempre in questo anche se ne hai di più specifici dopo questo – jon

+0

tvanfosson. Buona pesca. Ho appena realizzato questo esempio al volo. Hai ragione, potrei cogliere l'eccezione genitore generale in questo caso. Ma sì, mi piacerebbe un modo per catturare più tipi di eccezione non correlati in un blocco di cattura –

2

Se si utilizza VB.NET, è possibile astrarre il gestore degli errori nell'eccezione Aritmetica in una chiamata di metodo o funzione che restituisce sempre false.

Poi si potrebbe scrivere qualcosa di simile:

Catch ex as Arithmetic When HandleArithmetic() 
Catch ex as Exception 

End Try 

Non che io sosterrei tale uso, anche se ho visto consigliato per scopi di registrazione prima. Non credo ci sia un equivalente in C#.