Gestione e generazione di eccezioni

Le applicazioni devono essere in grado di gestire in modo coerente gli errori che si verificano durante l'esecuzione. Common Language Runtime fornisce un modello per notificare gli errori alle applicazioni in modo uniforme. In tutte le operazioni di .NET Framework gli errori vengono indicati mediante la generazione di eccezioni.

Di seguito sono elencate le diverse sezioni di questo argomento:

  • Eccezioni in .NET Framework

  • Eccezioni e metodi di gestione degli errori tradizionali

  • Modalità di gestione delle eccezioni nel runtime

  • Filtro delle eccezioni del runtime

  • Argomenti correlati

  • Riferimenti

Eccezioni in .NET Framework

Un'eccezione è una condizione di errore o un comportamento imprevisto riscontrato da un programma in esecuzione. Le eccezioni possono essere generate in caso di errori nel codice dell'applicazione o nel codice chiamato (ad esempio una libreria condivisa), in caso di risorse del sistema operativo non disponibili, di condizioni impreviste riscontrate da Common Language Runtime (ad esempio codice impossibile da verificare) e così via. L'applicazione è in grado di gestire alcune di queste condizioni, altre no. Sebbene sia possibile gestire gran parte delle eccezioni dell'applicazione, la maggior parte delle eccezioni di runtime risulta ingestibile.

In .NET Framework, un'eccezione è un oggetto che eredita dalla classe System.Exception. Le eccezioni vengono generate dalle aree di codice in cui si è verificato un problema. Ogni eccezione viene passata ai livelli superiori dello stack finché viene gestita dall'applicazione o si arresta il programma.

Torna all'inizio

Eccezioni emetodi di gestione degli errori tradizionali

In precedenza, il modello di gestione degli errori di un linguaggio si basava sul metodo specifico utilizzato da tale linguaggio per rilevare gli errori e individuarne i gestori oppure sul meccanismo di gestione degli errori fornito dal sistema operativo. Nel runtime la gestione delle eccezioni viene implementata con le seguenti modalità:

  • Indipendentemente dal linguaggio in cui vengono generate o gestite le singole eccezioni.

  • Senza la necessità di una sintassi di linguaggio apposita, ma con la possibilità per ciascun linguaggio di definire la propria sintassi.

  • Con la possibilità di generare eccezioni anche a livello di più processi e addirittura di più computer differenti.

Le eccezioni presentano vari vantaggi rispetto ad altri metodi di notifica degli errori, quali i codici restituiti. Gli errori vengono sempre rilevati. I valori non validi non continuano a propagarsi nel sistema. Non è necessario controllare i codici restituiti. È possibile aggiungere con facilità codice per la gestione delle eccezioni per aumentare l'affidabilità dei programmi. La gestione delle eccezioni nel runtime, infine, è più rapida rispetto alla gestione degli errori di C++ per Windows.

Dal momento che i thread di esecuzione riguardano normalmente blocchi di codice gestiti e non gestiti, il runtime può generare o rilevare eccezioni sia nel codice gestito che nel codice non gestito. Nel codice non gestito possono essere incluse sia eccezioni SEH C++ che HRESULT basati su COM.

Modalità di gestione delle eccezioni nel runtime

Nel runtime viene utilizzato un modello di gestione delle eccezioni basato su oggetti eccezione e blocchi di codice protetti. Quando si verifica un'eccezione viene creato un oggetto Exception per rappresentarla.

Nel runtime viene creata, per ciascun eseguibile, una tabella contenente informazioni sulle eccezioni. A ogni metodo dell'eseguibile è associata, nella tabella delle informazioni sulle eccezioni, una matrice di informazioni sulla gestione delle eccezioni, che può essere vuota. Ogni voce della matrice descrive un blocco di codice protetto, eventuali filtri di eccezioni associati a tale codice nonché eventuali gestori di eccezioni (istruzioni catch). Questa tabella delle eccezioni è estremamente efficiente e, finché non si verifica alcuna eccezione, non compromette in alcun modo le prestazioni, né in termini di tempo del processore né in termini di utilizzo della memoria. Le risorse vengono utilizzate solo quando ha luogo un'eccezione.

La tabella di informazioni sulle eccezioni rappresenta quattro tipi di gestori eccezioni per blocchi protetti:

  • Un gestore finally che viene eseguito a ogni uscita dal blocco, indipendentemente dal fatto che si verifichi per un normale flusso di controllo o in seguito a un'eccezione non gestita.

  • Un gestore fault che viene eseguito se si verifica un'eccezione, ma non al completamento del normale flusso del controllo.

  • Un gestore filtrato in base al tipo che gestisce tutte le eccezioni di una classe specificata o delle relative classi derivate.

  • Un gestore filtrato dall'utente che esegue codice specificato dall'utente per determinare se l'eccezione debba essere gestita dal gestore associato o passata al blocco protetto successivo.

In ciascun linguaggio questi gestori eccezioni vengono implementati in base alle specifiche in esso definite. Visual Basic, ad esempio, consente di accedere al gestore filtrato dall'utente tramite un confronto tra variabili (utilizzando la parola chiave When) nell'istruzione catch; C#, per contro, non implementa il gestore filtrato dall'utente.

Quando si verifica un'eccezione, nel runtime ha inizio un processo suddiviso in due fasi:

  1. Nella matrice viene cercato il primo blocco protetto che risponde alle seguenti caratteristiche:

    • Protegge un'area che include l'istruzione attualmente in esecuzione.

    • Contiene un gestore eccezioni oppure un filtro che gestisce l'eccezione.

  2. Se è presente un blocco che soddisfa queste condizioni, viene creato un oggetto Exception che descrive l'eccezione. Vengono quindi eseguite tutte le istruzioni finally o fault tra l'istruzione in cui si è verificata l'eccezione e l'istruzione che gestisce tale eccezione. L'ordine dei gestori di eccezioni è importante, dal momento che il gestore più interno viene valutato per primo. Si noti inoltre che i gestori eccezioni sono in grado di accedere alle variabili locali e alla memoria locale della routine che intercetta l'eccezione, ma vanno persi gli eventuali valori dei livelli intermedi dello stack presenti al momento della generazione dell'eccezione.

    Se nel metodo corrente non è disponibile alcun blocco che soddisfa le condizioni indicate, la ricerca verrà effettuata in ciascun chiamante del metodo corrente, risalendo via via, in questo modo, i vari livelli dello stack. Se anche la ricerca effettuata tra i chiamanti ha esito negativo, verrà consentito al debugger di accedere all'eccezione. Se il debugger non è associabile all'eccezione, verrà generato l'evento AppDomain.UnhandledException. Se non è presente alcun listener per l'evento, nel runtime verrà scaricata una traccia dello stack e l'applicazione verrà terminata.

Torna all'inizio

Filtro delle eccezioni del runtime

È possibile filtrare le eccezioni intercettate e gestite in base al tipo o ad altri criteri definiti dall'utente.

I gestori filtrati in base al tipo gestiscono un tipo particolare di eccezione o le classi da esso derivate. Nell'esempio che segue viene illustrato un gestore filtrato in base al tipo progettato per rilevare un'eccezione specifica, in questo caso FileNotFoundException.

Catch e As FileNotFoundException
    Console.WriteLine("[Data File Missing] {0}", e)
catch (FileNotFoundException e)
{
    Console.WriteLine("[Data File Missing] {0}", e);
}
catch (FileNotFoundException^ e)
{
    Console::WriteLine("[Data File Missing] {0}", e);
}

I gestori eccezioni filtrati dall'utente intercettano e gestiscono le eccezioni in base a requisiti definiti dall'utente per le singole eccezioni. Per ulteriori informazioni su questo tipo di filtro delle eccezioni, vedere Utilizzo di eccezioni specifiche in un blocco catch.

Torna all'inizio

Argomenti correlati

Titolo

Descrizione

Classe e proprietà dell'eccezione

Vengono descritti gli elementi di un oggetto eccezione.

Gerarchia delle eccezioni

Vengono descritte le eccezioni da cui deriva la maggior parte delle eccezioni.

Nozioni fondamentali sulla gestione delle eccezioni

Viene illustrato come gestire le eccezioni tramite istruzioni catch, throw e finally.

Suggerimenti per gestire le eccezioni

Vengono descritti alcuni metodi che è consigliabile adottare per la gestione delle eccezioni.

Gestione di eccezioni per interoperabilità COM

Viene descritto come gestire le eccezioni generate e intercettate in codice non gestito.

Procedura: eseguire il mapping di HRESULT ed eccezioni

Viene descritto il mapping delle eccezioni tra codice gestito e non gestito.

Torna all'inizio

Riferimenti

System.Exception

System.ApplicationException

System.SystemException