C#Programmazione

Eccezioni

Un’applicazione può smettere di funzionare per diversi motivi come ad esempio un errore di sistema, un errore di programmazione o semplicemente una errore da parte dell’utente.

Il meccanismo delle eccezioni permette di separare la parte di codice che identifica gli errori da quella che li gestisce. Un’eccezione è un’istanza di una classe derivata da System.Exception, viene creata quando si verifica una certa situazione eccezionale d’errore. Per eseguire queste attività vengono messe a disposizione parole chiave che consentono di catturare (ma anche generare) eccezioni.

  • try – blocco di codice che può generare un’eccezione;
  • catch – blocco di codice dedicato alla gestione delle eccezioni;
  • finally – blocco di codice da eseguire a prescindere dal verificarsi o meno di un’eccezione;
  • trow – genera una nuova eccezione;
try
{
   // codice che può generare un’eccezione
}
catch
{
   // codice da eseguire se si verifica un’eccezione
}

Questo esempio è il modo più generico che permette di catturare qualunque tipo di eccezione, possiamo anche specificare il tipo di eccezione:

catch(TipoEccezione [variabile])

catch(DivideByZeroException dex)

In questo caso viene gestita l’eccezione “divisione per zero” e dex contiene informazioni testuali sull’eccezione stessa.

All’interno di un blocco try si possono generare diverse condizione di errore, quindi possiamo specificare più blocchi catch che gestiranno ognuno un’eccezione diversa. Alla fine possiamo aggiungere un blocco catch generico per catturare qualsiasi altro tipo.

Quando si verifica un’eccezione il sistema cerca di trovare il blocco catch più vicino adeguato a gestirla, potrebbe non essere nello stesso blocco di esecuzione in cui la gestione si è originata.

Possiamo catturare un’eccezione al verificarsi di una condizione specificata con la parola chiave when. In questo esempio il blocco viene eseguito solo se la proprietà Status assume il valore ProtocolError:

catch(WebException ex) when(ex.Status == WebExceptionStatus.ProtocolError)

Il blocco finally viene eseguito in qualsiasi caso, prima vengono gestiti eventuali blocchi catch. Lo scopo è quando una parte di codice deve essere eseguito in ogni caso, ad esempio per rilasciare risorse che consumano memoria o che necessitano una sorta di chiusura.

La classe madre di tuti i tipi di eccezioni è la classe System.Exception, le proprietà pubbliche sono:

  • Message – messaggio di testo che descrive l’eccezione;
  • StackTrace – forma testuale dello stack delle chiamate;
  • InnerException – eccezione interna che ha causato quella attuale;
  • TargetSite – il metodo che ha causato l’eccezione;
  • Source – ottiene o imposta il nome dell’oggetto o applicazione che ha causato l’eccezione;
  • HelpLink – un collegamento al file guida;
  • Data – dizionario chiave-valore;
  • HResult – valore numerico codificato assegnato a ogni eccezione;

Tipi di eccezioni comuni:

  • ArgumentException – uno degli argomenti di un metodo non è valido;
  • ArgumentNullException – un argomentodi un metodo è null;
  • ArgumentOutOfRangeException – un valore utilizzato come argomento non è fra quelli consentiti o nell’intervallo consentito;
  • ArithmeticException – eccezioni di tipo aritmetico;
  • DivideByZeroException – divisione intera per zero;
  • OverflowException – un’operazione ha dato come risultato un overflow;
  • NotFiniteNumberException – un valore a virgola mobile è un numero infinito;
  • FormatException – un argomento non ha il formato corretto previsto;
  • ArrayTypeMismatchException – un oggetto in un array non è del tipo corretto;
  • IndexOutOfRangeException – un indice utilizzato per acceder a una collezione è al di là della sua dimensione;
  • InvalidCastException – errore di conversione esplicita;
  • NullReferenceException – si tenta di accendere a un membro di un oggetto, ma questo è null;
  • OutOfMemoryException – memoria esaurita;
  • StackOverflowException – stack esaurito a causa di troppe chiamate;
  • TypeInitializationException – una classe non gestita all’interno del costruttore statico;
  • InvalidOperationException – un’operazione eseguita su un oggetto non consentita nello stato attuale;
  • IO.IOException – eccezioni di input/output;
  • IO.FileNotFoundException – il file da utilizzare non esiste;
  • NotImplementedException – metodo non implementato;

Un’eccezione può essere creata e lanciata da parte dello sviluppatore nel proprio codice, tramite throw generiamo l’eccezione indicandone anche l’istanza. Sfruttando l’eredità possiamo creare classi di eccezioni personalizzata.

Il rilancio dell’eccezione può essere utile quando non si vuole gestire l’eccezione ma si vuole crea, ad esempio, una sorta di log e procedere con la gestione in una catch più esterna. Ogni eccezione personalizzata dovrebbe avere almeno i seguenti costruttori:

Possiamo anche personalizzare l’eccezione aggiungendo altre proprietà, metodi e costrutti.

Quindi un metodo può lanciare l’eccezione passando al suo costrutto le informazioni aggiuntive: