Procedure consigliate per la gestione delle eccezioni in C #

La gestione delle eccezioni è la tecnica per gestire gli errori di runtime nel codice dell'applicazione. Fondamentalmente, hai due categorie di eccezioni: le eccezioni generate dall'applicazione e quelle generate dal runtime. Le eccezioni dovrebbero essere gestite con cura: dovresti avere una buona idea di come le eccezioni dovrebbero essere gestite e quando devono essere gestite nel tuo codice. In questo post presenterò alcuni suggerimenti e best practice per lavorare con le eccezioni in C #.

La classe base per tutte le eccezioni in .NET è Exception. Tutte le classi di eccezioni nella gerarchia delle eccezioni derivano direttamente o indirettamente da questa classe. Le classi ApplicationException e SystemException derivano dalla classe Exception. Common Language Runtime (CLR) genera un'istanza di un tipo derivato da SystemException quando si verifica un errore in fase di esecuzione. Tieni presente che non dovresti mai intercettare SystemException o lanciare un'istanza di SystemException nel codice dell'applicazione.

Quando si creano classi di eccezioni personalizzate, derivare sempre dalla classe Exception e non dalla classe ApplicationException. Uno dei motivi è che un'istanza di ApplicationException viene generata dall'applicazione e mai dal runtime. Nel lanciare un'istanza di ApplicationException nel codice, aumenteresti semplicemente lo stack di chiamate senza aggiungere molto valore.

È un approccio di progettazione errato utilizzare la gestione delle eccezioni per restituire informazioni da un metodo. Se stai restituendo dati sull'eccezione dal tuo metodo, il design della tua classe è sbagliato e dovrebbe essere rivisto. Notare che le eccezioni vengono riportate al livello superiore nella gerarchia delle chiamate al metodo e non è una buona pratica gestire le eccezioni in tutti i livelli dell'applicazione. È necessario gestire un'eccezione il più in alto possibile nella gerarchia delle chiamate: è possibile utilizzare un'eccezione nel livello di presentazione e visualizzare i messaggi appropriati all'utente per notificare l'esatto errore che si è verificato.

È necessario lanciare nuovamente un'eccezione quando si desidera eseguire il rollback di una transazione del database. È buona norma utilizzare eccezioni specifiche come FileNotFoundException, IOException, ecc. Quando si scrivono gestori di eccezioni e quindi un blocco catch generale alla fine con la classe Exception. Ciò garantirebbe di conoscere l'errore esatto o l'errore specifico che si è verificato. L'MSDN afferma: "La classe ApplicationException non fornisce informazioni sulla causa delle eccezioni. Nella maggior parte degli scenari, le istanze di questa classe non devono essere generate. Nei casi in cui viene creata un'istanza di questa classe, dovrebbe essere visualizzato un messaggio leggibile dall'uomo che descrive l'errore passato al costruttore. "

Dovresti usare i blocchi try - catch per gestire le eccezioni e utilizzare un blocco latest per ripulire le risorse usate nel tuo programma. Il blocco try conterrebbe codice che potrebbe sollevare un'eccezione, il blocco catch verrà utilizzato per gestire l'eccezione lanciata all'interno del blocco try e il blocco finalmente verrà utilizzato per deallocare le risorse utilizzate dal programma. Si noti che il blocco finalmente è garantito per essere eseguito indipendentemente dal fatto che si sia verificata o meno un'eccezione. Quindi, finalmente il blocco è il posto migliore nel codice per ripulire le risorse utilizzate dal programma.

Lo snippet di codice riportato di seguito mostra come utilizzare l'istruzione "using" per disporre le risorse. Notare che l'istruzione "using" è un equivalente di try - latest block.

public string Read(string fileName)

{

try

{

string data;

using (StreamReader streamReader = new StreamReader(fileName))

{

data = streamReader.ReadToEnd();

}

return data;

}

catch (Exception)

{

throw;

}

}

Lanciare eccezioni è costoso. È una cattiva pratica rilanciare le eccezioni: nel rilanciare le eccezioni si perde la traccia dello stack.

try

{

//Some code that might throw an exception

}

catch(Exception ex)

{

throw ex;

}

Utilizzare invece l'istruzione "throw" se non si desidera gestire l'eccezione nel gestore delle eccezioni e propagare l'eccezione verso l'alto nella gerarchia delle chiamate.

try

{

//Some code that might throw an exception

}

catch(Exception ex)

{

throw;

}

Non ingoiare mai eccezioni: non dovresti mai nascondere l'errore che si è verificato. È buona norma registrare le eccezioni nell'applicazione. Quando si registrano le eccezioni, è necessario registrare sempre l'istanza dell'eccezione in modo che venga registrata l'intera analisi dello stack e non solo il messaggio di eccezione. Ecco un esempio che lo illustra.

try

{

//Some code that might throw an exception

}

catch(Exception ex)

{

LogManager.Log(ex.ToString());

}

Non utilizzare mai le eccezioni per propagare o eseguire regole di business nella tua applicazione. È possibile evitare eccezioni nel codice utilizzando una logica di convalida appropriata. Le eccezioni dovrebbero nella maggior parte dei casi essere evitate: dovresti usarlo solo quando è necessario.

È possibile fare riferimento a questo articolo di MSDN per ulteriori informazioni.