Quando usare try/catch/finally
Come ho scritto nel mio libro sul Common Language Runtime, raramente è necessario usare il costrutto try/catch/finally nella sua interezza, il più delle volte si ricorre a un try/finally nidificato all'interno di un try/catch. Il motivo è la necessità di rilascio immediato delle risorse bloccate (operazione tipicamente svolta dalla finally), specialmente quando la gestione dell'errore potrebbe includere un'interazione con l'utente (si pensi a una segnalazione all'utente o comunque a un'operazione di I/O nel blocco catch).
Un caso "da manuale" di effettiva necessità del try/catch/finally è lo scenario in cui si debba reagire a una condizione di errore (con del codice specifico per questo caso) prima del rilascio delle risorse allocate. Per esempio, il codice che segue gestisce l'interazione tra un DataContext di LINQ e la transazione sulla connessione al DB.
db.LocalTransaction = db.Connection.BeginTransaction();
try {
db.SubmitChanges();
db.LocalTransaction.Commit();
db.AcceptChanges();
}
catch {
db.LocalTransaction.Abort();
throw;
}
finally {
db.LocalTransaction = null;
}
Chiaramente, l'esempio specifico può essere discutibile (si pensi a cosa implicherebbe un'eccezione in AcceptChanges...) ma l'idea di avere un try/catch all'interno di un try/finally (ciò che fa semanticamente il try/catch/finally) è qualcosa che ha dei reali scenari applicativi, anche se non è certo il caso più frequente di pattern usato nella gestione delle eccezioni.