Per visualizzare l'articolo in inglese, selezionare la casella di controllo Inglese. È possibile anche visualizzare il testo inglese in una finestra popup posizionando il puntatore del mouse sopra il testo.
Traduzione
Inglese

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.

In questo argomento sono incluse le seguenti sezioni:

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é non viene gestita dall'applicazione o non si arresta il programma.

Torna all'inizio

In precedenza, il modello di gestione degli errori di un linguaggio si basava sul metodo specifico usato 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.

Il runtime usa 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.

Il runtime crea, 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 usate solo quando ha luogo un'eccezione.

La tabella di informazioni sulle eccezioni rappresenta quattro tipi di gestori di 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 di 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 (usando la parola chiave When) nell'istruzione catch; C#, per contro, non implementa il gestore filtrato dall'utente.

Quando si verifica un'eccezione, il runtime avvia un processo suddiviso in due fasi:

  1. Il runtime cerca nella matrice il primo blocco protetto che risponde alle seguenti caratteristiche:

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

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

  2. Se è presente un blocco che soddisfa queste condizioni, il runtime crea un oggetto Exception che descrive l'eccezione. Il runtime esegue quindi 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 di eccezioni possono accedere alle variabili locali e alla memoria locale della routine che intercetta l'eccezione, ma vanno persi gli eventuali valori intermedi presenti al momento della generazione dell'eccezione.

    Se nel metodo corrente non è presente alcun blocco che soddisfa le condizioni indicate, il runtime esegue la ricerca 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, il runtime consentirà al debugger di accedere all'eccezione. Se il debugger non è associabile all'eccezione, il runtime genererà l'evento AppDomain.UnhandledException. Se non è presente alcun listener per l'evento, il runtime eseguirà il dump dell'analisi dello stack e terminerà l'applicazione.

Torna all'inizio

È 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. L'esempio seguente illustra un gestore filtrato in base al tipo progettato per rilevare un'eccezione specifica, in questo caso FileNotFoundException.

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

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

Torna all'inizio

Titolo

Descrizione

Classe e proprietà dell'eccezione

Descrive gli elementi di un oggetto eccezione.

Gerarchia delle eccezioni

Descrive le eccezioni da cui deriva la maggior parte delle eccezioni.

Nozioni fondamentali sulla gestione delle eccezioni

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

Suggerimenti per le eccezioni

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

Gestione di eccezioni per interoperabilità COM

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

How to: Map HRESULTs and Exceptions

Descrive il mapping delle eccezioni tra codice gestito e non gestito.

Mostra: