21 Eccezioni
21.1 Generale
Le eccezioni in C# offrono un modo strutturato, uniforme e indipendente dai tipi di gestione delle condizioni di errore a livello di sistema e a livello di applicazione.
21.2 Cause di eccezioni
Le eccezioni possono essere generate in due modi diversi.
- Un'istruzione
throw
(§13.10.6) genera un'eccezione immediatamente e incondizionato. Il controllo non raggiunge mai l'istruzione immediatamente successiva athrow
. - Alcune condizioni eccezionali che si verificano durante l'elaborazione di istruzioni ed espressioni C# causano la generazione di un'eccezione in determinate circostanze quando l'operazione non può essere completata normalmente. Vedere §21.5 per un elenco delle varie eccezioni che possono essere generate in questo modo.
Esempio: un'operazione di divisione integer (§12.10.3) genera un'eccezione
System.DivideByZeroException
se il denominatore è zero. esempio finale
21.3 La classe System.Exception
La System.Exception
classe è il tipo di base di tutte le eccezioni. Questa classe ha alcune proprietà rilevanti condivise da tutte le eccezioni:
Message
è una proprietà di sola lettura di tipostring
che contiene una descrizione leggibile del motivo dell'eccezione.InnerException
è una proprietà di sola lettura di tipoException
. Se il valore è diversonull
da , fa riferimento all'eccezione che ha causato l'eccezione corrente. In altre parole, l'eccezione corrente è stata generata in un blocco catch che gestisce .InnerException
) In caso contrario, il relativo valore ènull
, che indica che questa eccezione non è stata causata da un'altra eccezione. Il numero di oggetti eccezione concatenati in questo modo può essere arbitrario.
Il valore di queste proprietà può essere specificato nelle chiamate al costruttore dell'istanza per System.Exception
.
21.4 Modalità di gestione delle eccezioni
Le eccezioni vengono gestite da un'istruzione try
(§13.11).
Quando viene generata un'eccezione (§21.2), il sistema cerca la clausola catch più vicina in grado di gestire l'eccezione, come determinato dal tipo di runtime dell'eccezione. In primo luogo, il metodo corrente viene cercato un'istruzione racchiusa try
lessicalmente e le clausole associate catch
dell'istruzione try
vengono considerate in ordine. In caso di esito negativo, viene eseguita la ricerca di un'istruzione che racchiude try
in modo lessicale il punto della chiamata al metodo corrente. Questa ricerca continua fino a quando non viene trovata una catch
clausola in grado di gestire l'eccezione corrente, assegnando un nome a una classe di eccezione che è della stessa classe o di una classe base del tipo di runtime dell'eccezione generata. Una catch
clausola che non denomina una classe di eccezione può gestire qualsiasi eccezione.
Dopo aver trovato una clausola corrispondente catch
, il sistema prepara il trasferimento del controllo alla prima istruzione della catch
clausola . Prima dell'inizio dell'esecuzione catch
della clausola, il sistema esegue prima di tutto, in ordine, tutte finally
le clausole associate alle try
istruzioni più annidate che hanno rilevato l'eccezione.
Se non viene trovata alcuna clausola corrispondente catch
:
- Se la ricerca di una clausola corrispondente
catch
raggiunge un costruttore statico (§15.12) o un inizializzatore di campo statico, viene generata un'eccezioneSystem.TypeInitializationException
al punto che ha attivato la chiamata del costruttore statico. L'eccezione interna diSystem.TypeInitializationException
contiene l'eccezione generata originariamente. - In caso contrario, se si verifica un'eccezione durante l'esecuzione del finalizzatore e tale eccezione non viene intercettata, il comportamento non viene specificato.
- In caso contrario, se la ricerca di clausole corrispondenti
catch
raggiunge il codice che inizialmente ha avviato il thread, l'esecuzione del thread viene terminata. L'impatto di tale terminazione è definito dall'implementazione.
21.5 Classi di eccezioni comuni
Le eccezioni seguenti vengono generate da determinate operazioni C#.
Tipo di eccezione | Descrizione |
---|---|
System.ArithmeticException |
Classe di base per le eccezioni che si verificano durante operazioni aritmetiche, quali System.DivideByZeroException e System.OverflowException . |
System.ArrayTypeMismatchException |
Generata quando un archivio in una matrice ha esito negativo perché il tipo dell'elemento archiviato non è compatibile con il tipo della matrice. |
System.DivideByZeroException |
Generata quando si verifica un tentativo di dividere un valore integrale per zero. |
System.IndexOutOfRangeException |
Generata quando un tentativo di indicizzazione di una matrice tramite un indice minore di zero o all'esterno dei limiti della matrice. |
System.InvalidCastException |
Generata quando una conversione esplicita da un tipo di base o un'interfaccia a un tipo derivato ha esito negativo in fase di esecuzione. |
System.NullReferenceException |
Generata quando viene utilizzato un null riferimento in modo da rendere obbligatorio l'oggetto a cui si fa riferimento. |
System.OutOfMemoryException |
Generata quando un tentativo di allocare memoria (tramite new ) non riesce. |
System.OverflowException |
Generata quando si verifica un overflow di un'operazione aritmetica in un contesto checked . |
System.StackOverflowException |
Generata quando lo stack di esecuzione viene esaurito con troppe chiamate in sospeso; in genere indicativo di ricorsione molto profonda o non associato. |
System.TypeInitializationException |
Generata quando un costruttore statico o un inizializzatore di campo statico genera un'eccezione e non esiste alcuna catch clausola per intercettarla. |
ECMA C# draft specification