Try...Catch...Finally Istruzione (Visual Basic)
Fornisce un metodo per gestire alcuni o tutti i potenziali errori che potrebbero verificarsi in un determinato blocco di codice senza interrompere l’esecuzione del codice.
Sintassi
Try
[ tryStatements ]
[ Exit Try ]
[ Catch [ exception [ As type ] ] [ When expression ]
[ catchStatements ]
[ Exit Try ] ]
[ Catch ... ]
[ Finally
[ finallyStatements ] ]
End Try
Parti
Termine | Definizione |
---|---|
tryStatements |
Facoltativo. Istruzioni nelle quali potrebbe verificarsi un errore. Può essere un'istruzione composta. |
Catch |
Facoltativo. Diversi blocchi Catch consentiti. Se dovesse verificarsi un'eccezione durante l'elaborazione del blocco Try , ogni istruzione Catch verrà esaminata in ordine testuale per determinare se gestisca l'eccezione, con exception come rappresentazione dell'eccezione generata. |
exception |
Facoltativo. Qualsiasi nome di variabile. Il valore iniziale di exception corrisponde al valore dell'errore generato. Usato con Catch per specificare l'errore rilevato. Se omesso, l'istruzione Catch intercetta qualsiasi eccezione. |
type |
Facoltativo. Specifica il tipo di filtro di classe. Se il valore di exception è del tipo specificato da type o di un tipo derivato, l'identificatore viene associato all'oggetto eccezione. |
When |
Facoltativo. Un'istruzione Catch con una clausola When rileva le eccezioni solo quando expression restituisce True . Una clausola When viene applicata solo dopo aver controllato il tipo di eccezione, e expression potrebbe fare riferimento all'identificatore che rappresenta l'eccezione. |
expression |
Facoltativo. Deve essere implicitamente convertibile a Boolean . Qualsiasi espressione che descrive un filtro generico. Generalmente usato per filtrare in base al numero di errore. Usato con la parola chiave When per specificare le circostanze in cui l'errore è rilevato. |
catchStatements |
Facoltativo. Istruzioni per la gestione di errori che si verificano nel blocco associato Try . Può essere un'istruzione composta. |
Exit Try |
Facoltativo. Parola chiave che evade la struttura Try...Catch...Finally . L'esecuzione riprende con il codice immediatamente successivo all'istruzione End Try . L'istruzione Finally verrà comunque eseguita. Non consentito nei blocchi Finally . |
Finally |
Facoltativo. Un blocco Finally viene sempre eseguito quando l'esecuzione lascia qualsiasi parte dell'istruzione Try...Catch . |
finallyStatements |
Facoltativo. Istruzione/i eseguita/e dopo che l’elaborazione di tutti gli altri errori è completata. |
End Try |
Termina la struttura Try...Catch...Finally . |
Osservazioni:
Se si prevede che possa verificarsi una particolare eccezione in una particolare sezione di codice, inserire il codice in un blocco Try
e usare un blocco Catch
per mantenere il controllo e gestire la potenziale eccezione.
Un'istruzione Try…Catch
è costituita da un blocco Try
seguito da una o più clausole Catch
, che specificano i gestori per varie eccezioni. Quando viene generata un'eccezione in un blocco Try
, Visual Basic cerca l'istruzione Catch
che gestisce l'eccezione. Se non viene trovata un'istruzione corrispondente Catch
, Visual Basic esamina il metodo che ha chiamato il metodo corrente, e così via, sullo stack di chiamate. Se non viene trovato alcun blocco Catch
, Visual Basic mostra un messaggio di eccezione non gestita per l'utente e interrompe l'esecuzione del programma.
È possibile usare più di un'istruzione Catch
in un'istruzione Try…Catch
. In questo caso, l'ordine delle clausole Catch
è rilevante, poiché le clausole vengono esaminate in ordine. Catch le eccezioni più specifiche prima di quelle meno specifiche.
Le seguenti Catch
condizioni di istruzione sono le meno specifiche e tutte le catch eccezioni che derivano dalla Exception classe. È consigliabile usare generalmente una di queste varianti come ultimo blocco Catch
nella struttura Try...Catch...Finally
, dopo aver intercettato tutte le eccezioni specifiche previste. Il flusso di controllo non è mai in grado di raggiungere un blocco Catch
che segue una di queste varianti.
type
èException
, ad esempio:Catch ex As Exception
L'istruzione non ha alcuna variabile
exception
, ad esempio:Catch
Quando un'istruzione Try…Catch…Finally
è annidata in un altro blocco Try
, Visual Basic esamina innanzitutto ogni istruzione Catch
nel blocco Try
più interno. Se non viene trovata alcuna istruzione Catch
corrispondente, la ricerca procede alle istruzioni Catch
del blocco esterno Try…Catch…Finally
.
Le variabili locali di un blocco Try
non sono disponibili in un blocco Catch
, poiché si tratta di due blocchi separati. Se si desidera usare una variabile in più blocchi, dichiarare la variabile all'esterno della struttura Try...Catch...Finally
.
Suggerimento
L'istruzione Try…Catch…Finally
è disponibile come frammento di codice IntelliSense. In Gestione frammenti di codice, espandere Criteri di codice - Se, Per ogni, TryCatch, Proprietà, e così via, quindi Gestione degli errori (Eccezioni). Per altre informazioni, vedere Code Snippets.
Blocco Finally
Se una o più istruzioni devono essere eseguite prima di uscire dalla struttura Try
, usare un blocco Finally
. Il controllo passa al blocco Finally
subito prima che passi dall’esterno della struttura Try…Catch
. Questo vale anche nel caso in cui dovesse verificarsi un'eccezione in qualsiasi punto all’interno della struttura Try
.
Un blocco Finally
è utile per l'esecuzione di qualsiasi codice che debba essere necessariamente eseguito anche in presenza di un'eccezione. Il controllo viene passato al blocco Finally
indipendentemente dalla modalità di uscita del blocco Try...Catch
.
Il codice in un blocco Finally
viene eseguito anche se il codice rileva un'istruzione Return
in un blocco Try
o Catch
. Il controllo non passa da un blocco Try
o Catch
al Finally
corrispondente nei seguenti casi:
Viene rilevata un'Istruzione di entità finale nel blocco
Try
oCatch
.Un StackOverflowException viene generato nel blocco
Try
oCatch
.
Il trasferimento esplicito dell'esecuzione a un blocco Finally
non è valido. Il trasferimento dell'esecuzione da un Finally
blocco non è valido, salvo tramite un'eccezione.
Se un'istruzione Try
non contiene almeno un blocco Catch
, deve necessariamente contenere un blocco Finally
.
Suggerimento
Se non sono necessarie catch eccezioni specifiche, l'istruzione Using
si comporta come un Try…Finally
blocco e garantisce l'eliminazione delle risorse, indipendentemente dal modo in cui si esce dal blocco. Questo vale anche per un'eccezione non gestita. Per altre informazioni, vedere Istruzione using.
Argomento eccezione
L'argomento di Catch
bloccoexception
è un'istanza della classe Exception o di una classe derivante dalla classe Exception
. L'istanza della classe Exception
corrisponde all'errore che si è verificato nel blocco Try
.
Le proprietà dell'oggetto Exception
consentono di identificare la causa e la posizione di un'eccezione. Ad esempio, la proprietà StackTrace elenca i metodi chiamati che hanno condotto all'eccezione, consentendo di individuare dove si è verificato l'errore nel codice. Message restituisce un messaggio che descrive l’eccezione l'eccezione. HelpLink restituisce un collegamento a un file Guida pertinente. InnerException restituisce l'oggetto Exception
che ha causato la corrente eccezione, o restituisce Nothing
se non è presente alcun Exception
originale.
Considerazioni sull'uso di un'istruzione Try…Catch
Usare un'istruzione Try…Catch
solo per segnalare l'occorrenza di eventi di programma insoliti o imprevisti. Ciò dipende da diversi fattori, sono riportati di seguito:
L'intercettazione delle eccezioni in fase di esecuzione crea un sovraccarico aggiuntivo ed è probabile che sia più lenta rispetto al controllo preliminare per evitare eccezioni.
Se un blocco
Catch
non viene gestito correttamente, l'eccezione potrebbe non essere correttamente segnalata agli utenti.La gestione delle eccezioni rende un programma più complesso.
Non è sempre necessaria un'istruzione Try…Catch
per verificare la presenza di una potenziale condizione. Nel seguente esempio viene verificato se un file è esistente prima di tentare di aprirlo. In questo modo, si riduce la necessità di intercettare un'eccezione generata dal metodo OpenText.
Private Sub TextFileExample(ByVal filePath As String)
' Verify that the file exists.
If System.IO.File.Exists(filePath) = False Then
Console.Write("File Not Found: " & filePath)
Else
' Open the text file and display its contents.
Dim sr As System.IO.StreamReader =
System.IO.File.OpenText(filePath)
Console.Write(sr.ReadToEnd)
sr.Close()
End If
End Sub
Accertarsi che il codice in blocchi Catch
possa segnalare correttamente le eccezioni agli utenti, che sia tramite registrazione thread-safe o appositi messaggi. In caso contrario, le eccezioni potrebbero rimanere ignote.
Metodi asincroni
Se si contrassegna un metodo con il modificatore Async, è possibile usare l'operatore Await nel metodo. Un'istruzione con l'operatore Await
sospende l'esecuzione del metodo fino al completamento dell'attività attesa. L'attività rappresenta il lavoro attualmente in fase di esecuzione. Al termine dell'attività associata all'operatore Await
, l'esecuzione riprende nello stesso metodo. Per ulteriori informazioni, consultare Flusso di controllo in programmi asincroni.
Un'attività restituita da un metodo asincrono potrebbe terminare in uno stato di errore, indicando che è stata completata a causa di un'eccezione non gestita. Un'attività potrebbe anche terminare in uno stato di annullamento, comportando un'eccezione OperationCanceledException
generata dall'espressione await. Per catch entrambi i tipi di eccezione, inserire l'espressione Await
associata all'attività in un Try
blocco e catch l'eccezione Catch
nel blocco. Un esempio è fornito più avanti in questo argomento.
Un'attività potrebbe trovarsi in stato di errore perché più eccezioni sono responsabili dell'errore. Ad esempio, l'attività può essere il risultato di una chiamata a Task.WhenAll. Quando si attende tale attività, solo una delle eccezioni viene intercettata, ma non è possibile prevedere quale. Un esempio è fornito più avanti in questo argomento.
Un'espressione Await
non può trovarsi all'interno di un blocco Catch
o di un blocco Finally
.
Iteratori
Una funzione iteratore o funzione di accesso Get
esegue un'iterazione personalizzata su una raccolta. Un iteratore usa un'istruzione yield return per restituire ogni elemento della raccolta, uno alla volta. Per chiamare una funzione iteratore, usare l’Istruzione For Each... Next.
Un'istruzione Yield
può trovarsi all'interno di un blocco Try
. Un blocco Try
contenente un'istruzione Yield
può avere blocchi Catch
e un blocco Finally
. Per un esempio, vedere TryBlocchi.
Un'istruzione Yield
non può trovarsi all'interno di un blocco Catch
o di un blocco Finally
.
Se il corpo For Each
(all'esterno della funzione iteratore) genera un'eccezione, non viene eseguito un blocco Catch
ma bensì un blocco Finally
nella funzione iteratore. Un blocco Catch
all'interno di una funzione iteratore rileva solo le eccezioni che si verificano all'interno di essa.
Situazioni di attendibilità parziale
In situazioni di attendibilità parziale, ad esempio un'applicazione ospitata in una condivisione di rete, Try...Catch...Finally
non catch vengono eseguite eccezioni di sicurezza che si verificano prima che venga richiamato il metodo che contiene la chiamata. L’esempio seguente, quando inserito in una condivisione server ed eseguito da questa posizione, genera l'errore "System.Security.SecurityException: Request Failed.” Per ulteriori informazioni sulle eccezioni di sicurezza, consultare la classe SecurityException.
Try
Process.Start("http://www.microsoft.com")
Catch ex As Exception
Console.WriteLine("Can't load Web page" & vbCrLf & ex.Message)
End Try
In una situazione di attendibilità parziale, è necessario inserire l'istruzione Process.Start
in un Sub
distinto. La chiamata iniziale a Sub
avrà esito negativo. Ciò consente Try...Catch
di farlo catch prima che il Sub
che contiene Process.Start
viene avviato e l'eccezione di sicurezza prodotta.
Esempi
Struttura di Try...Catch...Finally
Il seguente esempio illustra la struttura dell’istruzione Try...Catch...Finally
.
Public Sub TryExample()
' Declare variables.
Dim x As Integer = 5
Dim y As Integer = 0
' Set up structured error handling.
Try
' Cause a "Divide by Zero" exception.
x = x \ y
' This statement does not execute because program
' control passes to the Catch block when the
' exception occurs.
Console.WriteLine("end of Try block")
Catch ex As Exception
' Show the exception's message.
Console.WriteLine(ex.Message)
' Show the stack trace, which is a list of methods
' that are currently executing.
Console.WriteLine("Stack Trace: " & vbCrLf & ex.StackTrace)
Finally
' This line executes whether or not the exception occurs.
Console.WriteLine("in Finally block")
End Try
End Sub
Eccezione in un metodo chiamato da un blocco Try
Nel seguente esempio, il metodo CreateException
genera un'eccezione NullReferenceException
. Il codice che genera l'eccezione non si trova in un blocco Try
. Pertanto, il metodo CreateException
non gestisce l'eccezione. Il metodo RunSample
gestisce l'eccezione poiché la chiamata al metodo CreateException
si trova in un blocco Try
.
L'esempio include istruzioni Catch
per vari tipi di eccezioni, ordinate dalla più specifica alla più generale.
Public Sub RunSample()
Try
CreateException()
Catch ex As System.IO.IOException
' Code that reacts to IOException.
Catch ex As NullReferenceException
Console.WriteLine("NullReferenceException: " & ex.Message)
Console.WriteLine("Stack Trace: " & vbCrLf & ex.StackTrace)
Catch ex As Exception
' Code that reacts to any other exception.
End Try
End Sub
Private Sub CreateException()
' This code throws a NullReferenceException.
Dim obj = Nothing
Dim prop = obj.Name
' This code also throws a NullReferenceException.
'Throw New NullReferenceException("Something happened.")
End Sub
L’istruzione Catch When
L’esempio seguente illustra come usare un'istruzione Catch When
per filtrare su un'espressione condizionale. Se l'espressione condizionale restituisce True
, il codice nel blocco Catch
viene eseguito.
Private Sub WhenExample()
Dim i As Integer = 5
Try
Throw New ArgumentException()
Catch e As OverflowException When i = 5
Console.WriteLine("First handler")
Catch e As ArgumentException When i = 4
Console.WriteLine("Second handler")
Catch When i = 5
Console.WriteLine("Third handler")
End Try
End Sub
' Output: Third handler
Istruzioni Try
annidate
Nel seguente esempio è presente un'istruzione Try…Catch
contenuta in un blocco Try
. Il blocco interno Catch
genera un'eccezione con la relativa proprietà InnerException
impostata sull'eccezione originale. Il blocco esterno Catch
segnala la propria eccezione e l'eccezione interna.
Private Sub InnerExceptionExample()
Try
Try
' Set a reference to a StringBuilder.
' The exception below does not occur if the commented
' out statement is used instead.
Dim sb As System.Text.StringBuilder
'Dim sb As New System.Text.StringBuilder
' Cause a NullReferenceException.
sb.Append("text")
Catch ex As Exception
' Throw a new exception that has the inner exception
' set to the original exception.
Throw New ApplicationException("Something happened :(", ex)
End Try
Catch ex2 As Exception
' Show the exception.
Console.WriteLine("Exception: " & ex2.Message)
Console.WriteLine(ex2.StackTrace)
' Show the inner exception, if one is present.
If ex2.InnerException IsNot Nothing Then
Console.WriteLine("Inner Exception: " & ex2.InnerException.Message)
Console.WriteLine(ex2.StackTrace)
End If
End Try
End Sub
Gestione delle eccezioni per metodi asincroni
L'esempio seguente illustra la gestione delle eccezioni per i metodi asincroni. Per catch un'eccezione che si applica a un'attività asincrona, l'espressione Await
si trova in un Try
blocco del chiamante e l'eccezione viene intercettata nel Catch
blocco.
Rimuovere il commento dalla riga Throw New Exception
nell'esempio per illustrare la gestione delle eccezioni. L‘eccezione viene intercettata nel blocco Catch
, la proprietà IsFaulted
dell'attività viene impostata su True
, e la proprietà Exception.InnerException
dell'attività viene impostata sull'eccezione.
Rimuovere il commento dalla riga Throw New OperationCancelledException
per illustrare cosa accade quando si annulla un processo asincrono. L'eccezione viene intercettata nel blocco Catch
e la proprietà IsCanceled
dell'attività viene impostata su True
. Tuttavia, in alcune condizioni che differiscono da questo esempio, la proprietà IsFaulted
dell'attività viene impostata su True
e IsCanceled
viene impostato su False
.
Public Async Function DoSomethingAsync() As Task
Dim theTask As Task(Of String) = DelayAsync()
Try
Dim result As String = Await theTask
Debug.WriteLine("Result: " & result)
Catch ex As Exception
Debug.WriteLine("Exception Message: " & ex.Message)
End Try
Debug.WriteLine("Task IsCanceled: " & theTask.IsCanceled)
Debug.WriteLine("Task IsFaulted: " & theTask.IsFaulted)
If theTask.Exception IsNot Nothing Then
Debug.WriteLine("Task Exception Message: " &
theTask.Exception.Message)
Debug.WriteLine("Task Inner Exception Message: " &
theTask.Exception.InnerException.Message)
End If
End Function
Private Async Function DelayAsync() As Task(Of String)
Await Task.Delay(100)
' Uncomment each of the following lines to
' demonstrate exception handling.
'Throw New OperationCanceledException("canceled")
'Throw New Exception("Something happened.")
Return "Done"
End Function
' Output when no exception is thrown in the awaited method:
' Result: Done
' Task IsCanceled: False
' Task IsFaulted: False
' Output when an Exception is thrown in the awaited method:
' Exception Message: Something happened.
' Task IsCanceled: False
' Task IsFaulted: True
' Task Exception Message: One or more errors occurred.
' Task Inner Exception Message: Something happened.
' Output when an OperationCanceledException or TaskCanceledException
' is thrown in the awaited method:
' Exception Message: canceled
' Task IsCanceled: True
' Task IsFaulted: False
Gestione di più eccezioni in metodi asincroni
Il seguente esempio illustra la gestione delle eccezioni dove più attività possono restituire più eccezioni. Il blocco Try
ha l'espressione Await
per l'attività restituita da Task.WhenAll. L'attività viene completata una volta completate le tre attività a cui si applica Task.WhenAll.
Ognuna delle tre attività genera un'eccezione. Il blocco Catch
esegue l'iterazione delle eccezioni presenti nella proprietà Exception.InnerExceptions
dell'attività restituita da Task.WhenAll
.
Public Async Function DoMultipleAsync() As Task
Dim theTask1 As Task = ExcAsync(info:="First Task")
Dim theTask2 As Task = ExcAsync(info:="Second Task")
Dim theTask3 As Task = ExcAsync(info:="Third Task")
Dim allTasks As Task = Task.WhenAll(theTask1, theTask2, theTask3)
Try
Await allTasks
Catch ex As Exception
Debug.WriteLine("Exception: " & ex.Message)
Debug.WriteLine("Task IsFaulted: " & allTasks.IsFaulted)
For Each inEx In allTasks.Exception.InnerExceptions
Debug.WriteLine("Task Inner Exception: " + inEx.Message)
Next
End Try
End Function
Private Async Function ExcAsync(info As String) As Task
Await Task.Delay(100)
Throw New Exception("Error-" & info)
End Function
' Output:
' Exception: Error-First Task
' Task IsFaulted: True
' Task Inner Exception: Error-First Task
' Task Inner Exception: Error-Second Task
' Task Inner Exception: Error-Third Task