2011-01-04 12 views
140

Quale:try/catch + utilizzando, giusta sintassi

using (var myObject = new MyClass()) 
{ 
    try 
    { 
     // something here... 
    } 
    catch(Exception ex) 
    { 
     // Handle exception 
    } 
} 

O

try 
{ 
    using (var myObject = new MyClass()) 
    { 
     // something here... 
    } 
} 
catch(Exception ex) 
{ 
    // Handle exception 
} 
+6

Solo una nota: bisogna stare attenti al sole eccezioni di cattura che possono essere effettivamente _handled_ (corretti), tranne che per la registrazione, o avvolgendoli. –

+1

Si prega di tenere presente che anche l'ultimo '}' dell'istruzione 'using' può generare un'eccezione [come ricordato qui] (https://msdn.microsoft.com/en-us/library/aa355056%28v=vs. 110% 29.aspx). –

+0

TIL che il debugger (in VS) non chiamerà il metodo dispose se si utilizza il primo blocco di codice. Poiché l'istruzione using può lanciare un'eccezione, mi aiuta a usare il secondo blocco per garantire che il 'dispose 'abbia chiamato il metodo dispose. – ShooShoSha

risposta

70

io preferisco la seconda. Può anche trattenere errori relativi alla creazione dell'oggetto.

+10

Non sono d'accordo con questo consiglio. Se ti aspetti che la creazione dell'oggetto generi un errore, allora qualsiasi gestione di tale eccezione * deve * uscire. Se c'è qualche domanda su dove dovrebbe andare la gestione, allora l'eccezione che ci si aspetta deve essere qualcos'altro, a meno che non si stia sostenendo l'eventualità di un'eccezione casuale che può essere anticipata o meno, che è un classico anti-pattern (al di fuori di una gestore di eccezioni non gestito del processo o del thread). –

+1

@Jeffrey: L'approccio che ho descritto mi è servito bene e lo sto facendo da molto tempo. Nessuno ha detto nulla sull'aspettarsi che la creazione dell'oggetto * fallisca. Ma avvolgendo un'operazione che potrebbe * potenzialmente * fallire in un blocco 'try', che consente di inserire un messaggio di errore se qualcosa non funziona, il programma ora ha la capacità di recuperare e informare l'utente. –

+0

La tua risposta è corretta ma continua il suggerimento che il try/catch _has_ sia lì (immediatamente) in ogni momento. –

8

Entrambi sono sintassi valida. Dipende davvero da cosa vuoi fare: se vuoi catturare gli errori relativi alla creazione/eliminazione dell'oggetto, usa il secondo. In caso contrario, utilizzare il primo.

6

C'è una cosa importante, che chiamerò qui: Il primo sarà non cattura alcuna eccezione derivante chiamando il costruttore MyClass.

27

Dal momento che un blocco utilizzando è solo una semplificazione della sintassi di un try/finally (MSDN), personalmente mi piacerebbe andare con il seguente, anche se dubito che sia significativamente diversa da quella seconda opzione:

MyClass myObject = null; 
try { 
    myObject = new MyClass(); 
    //important stuff 
} catch (Exception ex) { 
    //handle exception 
} finally { 
    if(myObject is IDisposable) myObject.Dispose(); 
} 
+3

Perché pensi che l'aggiunta di un blocco 'finally' sia preferibile all'istruzione' using'? –

+7

L'aggiunta di un blocco 'finally' che dispone di un oggetto IDisposable è ciò che fa un'istruzione' using'. Personalmente, mi piace questo invece del blocco 'using' incorporato perché penso che dichiari più chiaramente dove sta accadendo tutto, e che è tutto sullo stesso" livello ". Mi piace anche più di alcuni blocchi 'using' integrati ... ma è solo una mia preferenza. – chezy525

+4

Se si implementa molta gestione delle eccezioni, è necessario divertirsi davvero digitando! Quella parola chiave "using" è in circolazione da un po 'e il suo significato è abbastanza chiaro per me. E usarlo aiuta a rendere il resto del mio codice più chiaro mantenendo la quantità di confusione al minimo. –

17

E ' dipende. Se si utilizza Windows Communication Foundation (WCF), using(...) { try... } non funzionerà correttamente se il proxy nell'istruzione using si trova nello stato di eccezione, ovvero lo smaltimento di questo proxy causerà un'altra eccezione.

Personalmente, credo nell'approccio alla gestione minima, cioè gestisco solo l'eccezione di cui sei a conoscenza al momento dell'esecuzione. In altre parole, se si sa che l'inizializzazione di una variabile in using può generare una particolare eccezione, la avvolgo con try-catch. Allo stesso modo, se all'interno del corpo using può accadere qualcosa, che non è direttamente correlato alla variabile in using, allora lo avvolgo con un altro try per quella particolare eccezione. Uso raramente Exception nel mio catch es.

Ma mi piace IDisposable e using anche se quindi forse di parte.

16

Se la dichiarazione di cattura deve accedere alla variabile dichiarata in un'istruzione using, quindi all'interno è l'unica opzione.

Se l'istruzione catch richiede l'oggetto a cui si fa riferimento nell'uso prima che venga eliminato, all'interno è l'unica opzione.

Se la dichiarazione di cattura prende un'azione di durata sconosciuta, come visualizzare un messaggio per l'utente e si desidera disporre delle risorse prima che ciò accada, quindi all'esterno è l'opzione migliore.

Ogni volta che ho uno scenerio simile a questo, il blocco try-catch si trova di solito in un altro metodo più in alto nello stack di chiamate dall'utilizzo. Non è tipico per un metodo sapere come gestire le eccezioni che si verificano al suo interno in questo modo.

Quindi la mia raccomandazione generale è fuori dall'esterno.

private void saveButton_Click(object sender, EventArgs args) 
{ 
    try 
    { 
     SaveFile(myFile); // The using statement will appear somewhere in here. 
    } 
    catch (IOException ex) 
    { 
     MessageBox.Show(ex.Message); 
    } 
} 
1

Se l'oggetto che si inizializza nella Utilizzando blocco() potrebbe gettare alcuna eccezione allora si dovrebbe andare per la seconda sintassi altrimenti sia l'altrettanto valida.

Nel mio scenario, ho dovuto aprire un file e stavo passando filePath nel costruttore dell'oggetto che stavo inizializzando nel blocco Using() e potrebbe generare un'eccezione se filePath è sbagliato/vuoto. Quindi in questo caso, la seconda sintassi ha senso.

mio codice di esempio: -

try 
{ 
    using (var obj= new MyClass("fileName.extension")) 
    { 

    } 
} 
catch(Exception ex) 
{ 
    //Take actions according to the exception. 
} 
Problemi correlati