2012-04-17 15 views
16

So che l'istruzione Using elimina l'oggetto che si sta creando. Come se volevo fare qualcosa di simile:Catching Exception inside Using statement

Using(SqlConnection conn = new SqlConnection(connString)) 
    { 
     //some code 
     //How to show the users if conn is not opened up or generated some kind of error? 
    } 

Come mostrare agli utenti se conn non viene aperto o generato qualche tipo di errore?

+0

Surround con un blocco TryCatch – SimpleVar

+0

con 'try/catch'. – Jon

+0

Potrebbe chiarire la tua domanda? sicuro di cosa stai chiedendo qui. – Tejs

risposta

8

using non offre alcuna backdoor nello catch.

semplicemente espandere manualmente (inutile avere il try/catch all'interno del usando IMO):

SqlConnection conn = null; 

try 
{ 
    conn = new SqlConnection(""); 
} 
catch ... 
{ 

} 
finally 
{ 
    if (conn != null) 
     conn.Dispose(); 
} 

prediligo questo oltre avvolgendo il using in un try-catch o incorporare un try-catch nel using la maggior parte del tempo per evitare che il codice finisca con uno try-catch nidificato una volta compilato. Se hai solo bisogno di coprire un sottogruppo molto piccolo di un grande pezzo di codice all'interno di uno using, tuttavia, sarei più granulare e lo incorporo.

+0

La semantica @marc_s, il punto è che "usare" non offre alcun supporto, devi tornare indietro per provare/catturare. –

+2

@marc_s Il mio modo compila solo un tentativo/cattura, altrimenti ognuno per conto proprio. Il mio offre non meno supporto di "usare". –

22

Non c'è niente di speciale su codice scritto all'interno di un blocco using - basta usare un try.catch per gestire le eccezioni:

using(SqlConnection conn = new SqlConnection(connString)) 
{ 
    try 
    { 
     conn.Open(); 
     // do more stuff here...... 

    } 
    catch(SqlException sqlEx) 
    { 
     // log error and possibly show to user in a MessageBox or something else 
    } 
} 

Il using(...) { ... } blocco stesso è stato progettato solo al fine di garantire che la risorsa/oggetto che "incapsula" è correttamente smaltito quando non è più necessario. Non c'è nulla che tu possa fare con l'istruzione using per far sì che gestisca gli errori.

Quindi, se si prevede che solo la creazione dell'oggetto potrebbe fallire, allora si avrebbe dovuto mettere l'intero using blocco all'interno del blocco try ... catch, o ripiegare ad un blocco try ... catch ... finally e garantire il corretto smaltimento te stesso (come Adam ha suggerito nel suo risposta).

+0

Perché stiamo usando try/catch all'interno Using? –

+5

+1 ... non solo non è speciale ma è anche una buona pratica usare try/catch in una istruzione using. Smaltire oggetti e gestire le eccezioni sono concetti diversi. –

+2

@Raj Perché un Try/Catch è come si cattura un'eccezione. A Usare è solo una Prova/Finalmente (senza cattura). Se la tua domanda è perché non è fuori dall'uso, è perché la creazione della connessione non causa un errore, l'apertura è. – Servy

2

Questo è esattamente come lo faresti senza.

using(SqlConnection conn = new SqlConnection(connString)) 
{ 
    try{ 
    //some code 
    } 
    catch(SqlException e) 
    MessageBox.Show(e.Message); 
} 
3

Proprio in modo normale:

In entrambi i

try 
{ 
    using(SqlConnection conn = new SqlConnection(connString)) 
    { 
     //some code   
    } 
} 
catch (Exception exc) 
{ 
    //handle error 
} 

o

using(SqlConnection conn = new SqlConnection(connString)) 
{ 
    try 
    { 
     //some code 
    } 
    catch (Exception exc) 
    { 
     //handle error 
    }     
} 
+0

Qual è il punto di utilizzo di Try/Catch inside Using? –

+2

@Widor: Questo non funzionerà se viene lanciata un'eccezione a 'SqlConnection conn = new ...' – xbonez

+0

Bene, dipende da ciò che si fa lì - forse si vuole catturare un'eccezione potenziale diversa (non correlata a SQL) per esempio. – Widor

0

Non lo fanno all'interno del using

try 
{ 
    using(SqlConnection conn = new SqlConnection(connString)) 
    { 
     // Some code for when "conn" is succesfully instantiated 
    } 
} 
catch (SomeSpecificConnectionInstantiationException ex) 
{ 
    // Use ex to handle a bizarre instantiation exception? 
}  
+0

Puoi scrivere try/catch all'interno dell'utilizzo. Credo! –

+1

È possibile ma, per non rilevare un'eccezione nell'uso dell'istanza – Jodrell

+0

@Jodrell Ma un SqlConnection non genera un'eccezione nel suo costruttore. L'unica eccezione che probabilmente otterrai è nell'espressione per il parametro. – Servy

8
class SqlConnection 
{ 
    using(sqlConnection) 
    { 

    } 
} 

class Consumer 
{ 
    try 
    { 

    } 
    catch(SqlException) 
    { 

    } 

} 

Spetta al consumatore della classe decidere cosa fare con l'eccezione.

6

Come altre risposte hanno dichiarato, è sufficiente aggiungere un normale try/catch.

Tuttavia, vorrei aggiungere che questo è sbagliato posto mettere che try/catch, soprattutto se il tuo obiettivo è "mostrare gli utenti" un messaggio. Lascia che l'eccezione si verifichi a questo livello e permetti che bolla lo stack al codice che è in una posizione migliore per sapere come rispondere ad esso.

In altre parole, lasciare il codice di esempio così com'è. Non aggiungere nulla di nuovo ... a quel metodo. Ma forse il codice che chiama questo metodo dovrebbe pensare a come gestire un'eccezione ... qualsiasi eccezione ... dal database.

+0

Puoi mostrarmi un esempio? O qualsiasi link che sia sufficiente. Grazie! –

+0

@Raj Controlla la mia risposta. Questo è quello che ho menzionato nella mia risposta. – Sandeep

-2

È consigliabile utilizzare try {} catch() {} nell'istruzione using se si desidera rilevare un'eccezione generata dal codice all'interno del blocco using. Ora, prendi in considerazione i seguenti due esempi: questo spiega perché il blocco try-catch all'interno dell'istruzione using è una buona pratica.

Esempio 1

 try{ 
      using(SomeObject so = new SomeObject){ 
       // Perform some tasks 
      } 
     }catch(SomeException objSomeException){ 
      // Perform some actions, if exception occurs 
     } 

Esempio 2

 using(SomeObject so = new SomeObject){ 
      try{  
       // Perform some tasks 
       }catch(SomeException objSomeException){ 
        // Perform some actions, if exception occurs 
       } 
     } 

Ora, se si verifica un'eccezione durante l'esecuzione di alcune attività all'interno della istruzione using, saranno entrambi ad esempio avere la stesso risultato. La semplice risposta è no, motivo ???

Quando si verifica un'eccezione nell'esempio 1, viene catturata dal blocco catch, senza raggiungere la fine del blocco using. Pertanto, someObject nell'esempio 1 non verrà eliminato correttamente. Anche se CLR è generoso (su cui non dovresti contare) - la memoria utilizzata da someObject nell'esempio 1 non verrà ripristinata (o il massimo finirà nella raccolta GC di Generazione 2).

Nel caso dell'esempio 2, il blocco di cattura si trova all'interno dell'istruzione using. Ciò significa che l'esecuzione raggiungerà la fine del blocco using. Pertanto, il tuo oggetto sarà eliminato e non dovrai preoccuparti della perdita di memoria (deterioramento,

+4

Questo è sbagliato. Se si verifica un errore nell'utilizzo, l'oggetto sarà eliminato dal blocco implicito 'finally' di' using', e l'eccezione sarà gestita dal 'catch' esterno. Nel secondo caso l'eccezione sarà gestita dal blocco interno 'catch', e l'implicito' finally' dell'uso 'lo eliminerà in seguito. Quindi, l'unica differenza è che nel secondo campione 'catch' l'oggetto è ancora disponibile, quindi puoi ancora usarlo per gestire l'eccezione. Nel primo esempio, l'oggetto non sarà più disponibile nel blocco catch. Niente più differenze. – JotaBe

0

Quando si incorpora il blocco using() all'interno di try/catch, il blocco using() garantisce effettivamente che Dispose Tuttavia, se il codice non gestito in qualsiasi punto all'interno del blocco utilizza genera un'eccezione, l'uso di() lo mangerà e non raggiungerà il problema. Utilizza try/catch nel blocco using(), salta using() e fai un try/catch/finally, o usa la sintassi dispari "using() try" con un blocco catch (che ti lascia con un numero dispari di parentesi ed è probabile che confonda i diavoli di programmatori di medio livello che successivamente incontreranno