Gerarchia delle Eccezioni in C#
- Nel .NET Framework, le eccezioni sono gestite attraverso una gerarchia di classi che ereditano da
Exception
. - La classe base per tutte le eccezioni è
System.Exception
, da cui derivanoApplicationException
eSystemException
. - Le eccezioni possono essere nidificate, creando una catena di eccezioni che fornisce informazioni dettagliate sugli errori.
- È importante utilizzare le eccezioni di applicazione per gestire errori specifici dell'applicazione, mentre le eccezioni di sistema sono riservate al framework e agli errori critici.
- Le eccezioni di sistema come
StackOverflowException
eOutOfMemoryException
indicano errori gravi che spesso non possono essere recuperati, mentre le eccezioni di applicazione possono essere utilizzate per gestire errori specifici e prevedibili nel codice.
Gerarchia delle Eccezioni
Ci sono due tipi di eccezioni nel .NET Framework: eccezioni lanciate dalle applicazioni che sviluppiamo (ApplicationException
) ed eccezioni lanciate dal runtime (SystemException
).
Ognuna di queste è una classe base per una gerarchia di classi di eccezioni:
Poiché tutte queste classi hanno caratteristiche diverse, le esamineremo una per una.
La Classe Exception
Nel .NET Framework, Exception
è la classe base per tutte le eccezioni.
Diverse classi ereditano direttamente da essa, incluse ApplicationException
e SystemException
. Queste due classi sono classi base per quasi tutte le eccezioni che si verificano durante l'esecuzione del programma.
La classe Exception
contiene una copia dello stack di chiamata al momento in cui l'istanza dell'eccezione è stata creata. La classe ha anche un messaggio (solitamente) breve che descrive l'errore (riempito dal metodo che genera l'eccezione).
Ogni eccezione può avere un'eccezione nidificata anche talvolta chiamata eccezione interna o eccezione avvolta.
La capacità di nidificare un'eccezione all'interno di un'altra eccezione è molto utile in alcuni casi e consente alle eccezioni di essere collegate nella cosiddetta catena di eccezioni o exception chain. In questo modo, possiamo ottenere informazioni più dettagliate su cosa è andato storto nel programma.
La Classe System.Exception
Ecco come appare la classe System.Exception
:
[SerializableAttribute]
[ComVisibleAttribute(true)]
[ClassInterfaceAttribute(ClassInterfaceType.None)]
public class Exception : ISerializable, _Exception
{
public Exception();
public Exception(string message);
public Exception(string message, Exception innerException);
public virtual IDictionary Data { get; }
public virtual string HelpLink { get; set; }
protected int HResult { get; set; }
public Exception InnerException { get; }
public virtual string Message { get; }
public virtual string Source { get; set; }
public virtual string StackTrace { get; }
public MethodBase TargetSite { get; }
public virtual Exception GetBaseException();
}
La specifica completa della classe Exception
fornita sopra è complessa da spiegare, quindi discuteremo solo i suoi metodi e proprietà più importanti poiché vengono ereditati da tutte le eccezioni nel .NET Framework.
-
Abbiamo tre costruttori con diverse combinazioni per messaggio ed eccezione interna:
- Il primo costruttore crea un'istanza di
Exception
senza messaggio o eccezione interna. - Il secondo accetta un messaggio di errore come parametro.
- Il terzo accetta sia un messaggio di errore che un'eccezione interna.
- Il primo costruttore crea un'istanza di
-
La proprietà
Message
restituisce una descrizione testuale dell'eccezione.Ad esempio, se l'eccezione è
FileNotFoundException
, il messaggio potrebbe fornire informazioni su quale file non è stato trovato. Nella maggior parte dei casi, il codice che genera l'eccezione passa il messaggio nel costruttore. Una volta impostata, la proprietàMessage
non può essere modificata. -
La proprietà
InnerException
restituisce l'eccezione interna (avvolta, annidata) onull
se tale eccezione non esiste. -
Il metodo
GetBaseException()
restituisce l'eccezione più interna da una catena di eccezioni data.Per definizione, chiamare questo metodo per ogni eccezione all'interno di una catena di eccezioni produrrà sempre lo stesso risultato – la prima eccezione che si è verificata.
-
La proprietà
StackTrace
restituisce informazioni per l'intero stack contenuto nell'eccezione (abbiamo già visto come appare questa informazione).
Eccezioni di Sistema e di Applicazione
Le eccezioni in .NET sono di due tipi: di sistema e di applicazione.
Le eccezioni di sistema sono definite nelle librerie .NET e sono utilizzate dal framework, mentre le eccezioni di applicazione sono definite dagli sviluppatori di applicazioni e sono utilizzate dal software applicativo.
Quando noi, come sviluppatori, progettiamo le nostre classi di eccezione, è una buona pratica ereditare da ApplicationException
e non direttamente da SystemException
(o anche peggio, direttamente da Exception
). SystemException
dovrebbe essere ereditata solo internamente all'interno del .NET Framework.
Alcune delle peggiori eccezioni di sistema includono ExecutionEngineException
(che viene lanciata su errore interno all'interno del CLR), StackOverflowException
(overflow dello stack di chiamata, molto probabilmente dovuto a ricorsione infinita) e OutOfMemoryException
(memoria insufficiente). In tutti questi casi, la nostra applicazione difficilmente potrebbe recuperare o reagire in qualche modo ragionevole. Più frequentemente, quando tale eccezione si verifica, l'applicazione semplicemente si blocca.
Le eccezioni relative all'interazione con componenti esterni (come i componenti COM) ereditano da ExternalException
. Esempi sono COMException
e Win32Exception
.