2013-08-11 30 views
6

Qual è la differenza tra Catch(Exception) e Catch(Exception ex). Posso vedere entrambi che mi danno un risultato previsto. Allora qual è la differenza attuale? Quale è raccomandato?Differenza tra catch (Exception) e Catch (eccezione ex)

Supponiamo che il codice sia di seguito.

int a = 1, b = 0; 
try 
{ 
    int c = a/b; 
    Console.WriteLine(c); 
} 

Quale dei seguenti blocchi di cattura si consiglia di utilizzare? Qual è la differenza effettiva tra quelli?

catch (Exception ex) 
{ 
    Console.WriteLine(ex.Message); 
} 

O

catch (Exception) 
{ 
    Console.WriteLine("Oh NO!!"); 
} 
+0

Se non siete interessati a quello che stai recuperando eccezione (info sullo stack, il messaggio ecc) si può scrivere semplicemente 'catch {Console.WriteLine (" Oh No ");} – Steve

+1

La differenza è che avrai * qualche * idea del perché il tuo programma smette di funzionare correttamente nel 1 ° frammento. Nessuna in alcun modo nel secondo frammento. Il secondo modo è ciò che rende gli utenti SO porre domande come "non funziona, c'è stato un errore". Basta non scrivere codice come questo. –

+1

@Steve C'è una piccola differenza tra 'catch' e' catch (Exception) '. Il primo catturerà tutti gli oggetti di eccezione, il secondo catturerà solo gli oggetti di eccezione derivanti da "Eccezione". In C# puoi lanciare solo oggetti derivanti da 'Exception', ma il CLR supporta di più. – user1908061

risposta

3

Beh, catch(Exception ex) è proprio la stessa catch(Exception) con una differenza solo: in catch(Exception ex) abbiamo un accesso alla classe di eccezione (errore di causa) esempio. Di solito è necessario un'istanza classe di eccezione per stampare la messaggio originale:

try { 
    ... 
    } 
    catch (AppServerException e) { 
    Console.WriteLine("Application server failed to get data with the message:"); 
    Console.WriteLine(e.Message); // <- What's actually got wrong with it 
    } 

Se non è necessario l'istanza di classe di eccezioni, per esempio si prevede solo per consumare l'eccezione , la sintassi catch (Exception ex) è eccessivo e catch (Exception) è prefferable:

try { 
    c = a/b; 
    } 
    catch (DivideByZeroException) { 
    c = Int.MaxValue; // <- in case b = 0, let c be the maximum possible int 
    } 

Infine. non prendere classe generale Exception senza ri-throughing:

try { 
    int c = a/b; 
    } 
    catch (Exception) { // <- Never ever do this! 
    Console.WriteLine("Oh NO!!"); 
    } 

vuoi veramente codificare "qualunque errore (fumi verde dalla CPU incluso) avevano gionro basta stampare fuori 'Oh No' e continua"? Il modello con classe Exception è qualcosa di simile:

tran.Start(); 

    try { 
    ... 
    tran.Commit(); 
    } 
    catch (Exception) { 
    // Whatever had happened, let's first rollback the database transaction 
    tran.Rollback(); 

    Console.WriteLine("Oh NO!"); 

    throw; // <- re-throw the exception 
    } 
+1

Non sono d'accordo con "_Non catturi la classe di eccezione generale senza il re-lancio". e _ "Vuoi veramente scrivere il codice" qualunque errore ", basta stampare" Oh No "e continuare?". 1.A volte lo faccio 2. Ci sono altre cose che potrei voler fare (oltre al logging). È comune catturare 'Exception ex' nel codice. – mayu

+0

È 'DivideByZeroException' non' ZeroDivisonException' afaik. – mayu

3

è abbastanza semplice:

  • nel primo codice, è possibile intercettare l'eccezione e ottenere l'oggetto che rappresenta in modo da poter avere ulteriori informazioni su cosa è successo
  • nel secondo codice, si sa solo che è stata sollevata un'eccezione, ma non si ha maggiori informazioni a riguardo.

Cosa usare in realtà dipende dalla quantità di informazioni che si desidera avere sull'eccezione generata.

2

Se è necessario utilizzare l'eccezione all'interno del blocco catch, assegnare a Exception un nome; altrimenti, tienilo anonimo.

Ci sono situazioni in cui il blocco catch deve fare di più che mostrare semplicemente il messaggio di eccezione. Ad esempio, quando si rilevano eccezioni specifiche dell'applicazione, è possibile esaminare ulteriori elementi dell'oggetto di eccezione. Ecco un esempio ipotetico:

catch (ConnectToServerException cse) { 
    MessageBox.Show(string.Format(
     "Connection to server '{0}' failed. Use a name from the following list: {1}" 
    , cse.AttemptedConnectionServerName 
    , string.Join(", ", cse.AllowedServerNames) 
    )); 
} 

Il codice sopra presuppone che l'eccezione personalizzato ConnectToServerException ha una proprietà chiamata AttemptedConnectionServerName con il nome del server a cui si è tentato di connettersi, e una proprietà di enumerazione AllowedServerNames con i nomi dei disponibili server.

Ci sono anche situazioni in cui tutto ciò che devi sapere è che è appena avvenuta un'eccezione di un particolare tipo. In questo caso, non è necessario fornire una variabile denominata per questo.

0

Catch (Exception) fare la stessa cosa, in quanto è anche un tipo Exception.

Catch (Exception ex) rileva tutte le eccezioni e inoltre è possibile recuperare il messaggio tramite il suo riferimento.

L'utilizzo dipende dal requisito, se si desidera visualizzare il messaggio di eccezione, è possibile utilizzare ex.Message altrimenti Catch (Exception) sarà sufficiente.

0

Con catch(Exception) si specifica solo che tipo di eccezione si è maniglia andando in quel blocco catch (in questo caso, tutte le eccezioni che si alza, quindi sarebbe la stessa di appena catch)

Con catch(Exception ex) voi passare un'istanza dell'eccezione effettiva che viene sollevata, in modo da poter accedere alle proprietà dell'eccezione e fare qualcosa con le informazioni fornite.

0

La differenza è che verrà stampato Tentativo di divisione per zero. e l'altro stamperà Oh NO !!.

Gestione delle eccezioni è un problema complesso e dipende l'applicazione, ma qui ci sono alcune osservazioni di carattere generale:


In generale è meglio per fornire i gestori per specifiche eccezioni:

qualcosa di simile:

catch ({System.DivideByZeroException ex) 
{ 
    Console.WriteLine("Ops. I cannot divide by zero."); 
} 
catch ({System.Exception ex) 
{ 
    Console.WriteLine("There was an error during calculations: {0}", ex.Message); 
} 

Prima o poi troverete fuori t il cappello Console.WriteLine non è abbastanza buono e dovrai usare un logger per iniziare a usarlo prima.


Idealmente, se si decide di esporre i messaggi di errore prime per l'utente, si dovrebbe essere la stampa di tutti i messaggi nella catena eccezione o almeno quello che è più profondo.

Qualcosa di simile:

catch ({System.DivideByZeroException ex) 
{ 
    Console.WriteLine("Oops. I cannot divide by zero."); 
} 
catch ({System.Exception ex) 
{ 
    Console.WriteLine(GetExceptionMsgs(ex)); 
} 

...in another class... 
public static string GetExceptionMsgs(Exception ex) { 
    if(ex == null) { 
     return "No exception = no details"; 
    } 
    var sb = new StringBuilder(); 
    while(ex != null) { 
     sb.AppendLine(ex.Message); 
     ex = ex.InnerException; 
    } 
    return sb.ToString() 
} 
Problemi correlati