Condividi tramite


Istruzione Try...Catch...Finally (Visual Basic)

Consente di gestire alcuni o tutti i possibili errori che possono verificarsi in un determinato blocco di codice in esecuzione.

Try
    [ tryStatements ]
    [ Exit Try ]
[ Catch [ exception [ As type ] ] [ When expression ]
    [ catchStatements ]
    [ Exit Try ] ]
[ Catch ... ]
[ Finally
    [ finallyStatements ] ]
End Try

Parti

Termine

Definizione

tryStatements

Opzionale. Una o più istruzioni in cui può verificarsi un errore. Può trattarsi di un'istruzione composta.

Catch

Opzionale. Sono ammessi più blocchi Catch. Se durante l'elaborazione del blocco Try si verifica un'eccezione, ogni istruzione Catch viene esaminata in ordine testuale per stabilire se gestisce l'eccezione. L'eccezione generata è rappresentata da exception.

exception

Opzionale. Qualsiasi nome di variabile. Il valore iniziale di exception corrisponde al valore dell'errore generato. Viene utilizzata con Catch per specificare l'errore intercettato. Se omessa, l'istruzione Catch genera un'eccezione.

type

Opzionale. Consente di specificare il tipo di classe filtrato. Se il valore di exception è del tipo specificato da type o di un tipo derivato da questo, l'identificatore viene associato all'oggetto eccezione.

When

Opzionale. Un'istruzione Catch con una clausola When intercetta eccezioni solo quando expression restituisce True. Una clausola When viene applicata soltanto dopo il controllo del tipo di eccezione; expression può fare riferimento all'identificatore che indica l'eccezione.

expression

Opzionale. Deve essere convertibile in modo implicito in un valore di tipo Boolean. Qualsiasi espressione in cui è descritto un filtro generico. Utilizzato in genere per filtrare in base al numero di errore. Viene utilizzato con la parola chiave When per specificare le circostanze in cui è stato intercettato l'errore.

catchStatements

Opzionale. Una o più istruzioni per la gestione degli errori verificatisi nel blocco Try associato. Può trattarsi di un'istruzione composta.

Exit Try

Opzionale. Parola chiave con cui viene interrotta la struttura Try...Catch...Finally. L'esecuzione riprende con il codice immediatamente successivo all'istruzione End Try. Verrà eseguita l'istruzione Finally. Non ammessa nei blocchi Finally.

Finally

Opzionale. Blocco Finally che viene eseguito tutte le volte che l'esecuzione abbandona l'istruzione Try...Catch in un punto qualsiasi.

finallyStatements

Opzionale. Una o più istruzioni eseguite dopo l'elaborazione di tutti gli altri errori.

End Try

Consente di terminare la struttura Try...Catch...Finally.

Note

Se si prevede il verificarsi di una determinata eccezione nel corso di una particolare sezione di codice, inserire il codice in un blocco Try e utilizzare un blocco Catch per mantenere il controllo e gestire l'eccezione nel caso in cui si verifichi.

Un'istruzione Try…Catch è costituita da un blocco Try seguito da una o più clausole Catch, mediante le quali vengono specificati i gestori per diverse eccezioni. Quando viene generata un'eccezione in un blocco Try, tramite Visual Basic viene cercata l'istruzione Catch mediante la quale viene gestita l'eccezione. Se non viene individuata un'istruzione Catch corrispondente, il metodo mediante il quale è stata eseguita la chiamata al metodo corrente e così via lungo lo stack di chiamate viene esaminato da Visual Basic. Se non viene trovato alcun blocco Catch, in Visual Basic viene visualizzato un messaggio di eccezione non gestita e l'esecuzione del programma viene arrestata.

È possibile utilizzare più istruzioni Catch in un'istruzione Try…Catch. In tal caso, l'ordine delle clausole Catch è importante poiché vengono esaminate nell'ordine specificato. Vengono intercettate prima le eccezioni più specifiche, quindi quelle meno specifiche.

Le seguenti condizioni dell'istruzione Catch sono quelle meno specifiche e consentono di rilevare tutte le eccezioni che derivano dalla classe Exception. Di norma, si consiglia di utilizzare una di queste variazioni come ultimo blocco Catch nella struttura Try...Catch...Finally, una volta generate tutte le eccezioni specifiche previste. Il flusso di controllo non può raggiungere mai un blocco Catch che segue una di queste variazioni.

  • Il valore di type è Exception, ad esempio: Catch ex As Exception

  • Nell'istruzione non sono presenti variabili exception, ad esempio: Catch

Quando un'istruzione Try…Catch…Finally è annidata in un altro blocco Try, in Visual Basic viene esaminata dapprima ciascuna istruzione Catch nella parte più interna del blocco Try. Se non viene trovata alcuna istruzione Catch corrispondente, si continua la ricerca nelle istruzioni Catch del blocco Try…Catch…Finally esterno.

Le variabili locali di un blocco Try non sono disponibili in un blocco Catch in quanto rappresentano blocchi separati. Se si desidera utilizzare una variabile in più blocchi, dichiarare la variabile al di fuori della struttura Try...Catch...Finally.

Suggerimento

L'istruzione Try…Catch…Finally è disponibile come frammento di codice IntelliSense.In Gestione frammenti di codice espandere Modelli di codice - If, For Each, Try Catch, Property e così via, quindi Gestione errori (Eccezioni).Per ulteriori informazioni, vedere Frammenti di codice.

Blocco finally

Se si dispone di una o più istruzioni da eseguire prima di uscire dalla struttura Try, utilizzare un blocco Finally. Il controllo viene passato al blocco Finally appena prima dell'uscita dalla struttura Try…Catch. Il passaggio avviene anche se si verifica un'eccezione in qualsiasi posizione all'interno della struttura Try.

Un blocco Finally è utile per l'esecuzione di qualsiasi codice sia necessario eseguire persino in presenza di un'eccezione. Il controllo viene passato al blocco Finally, indipendentemente dalla modalità di uscita dal blocco Try...Catch.

Il codice incluso in un blocco Finally viene eseguito anche se si incontra un'istruzione Return in un blocco Try o Catch. Il controllo non viene passato da un blocco Try o Catch al blocco Finally corrispondente nei seguenti casi:

Non è valida in modo esplicito trasferire l'esecuzione in un blocco Finally. L'esecuzione di trasferimento da un blocco Finally non è valida, ma con un'eccezione.

Se un'istruzione Try non contiene almeno un blocco Catch, deve contenere un blocco Finally.

Suggerimento

Se non è necessario rilevare eccezioni specifiche, il comportamento dell'istruzione Using è identico a quello di un blocco Try…Finally e viene garantita l'eliminazione delle risorse, a prescindere dalla modalità di uscita dal blocco.Questo meccanismo è valido anche per le eccezioni non gestite.Per ulteriori informazioni, vedere Istruzione Using (Visual Basic).

Argomento Exception

L'argomento exception del blocco Catch è un'istanza della classe Exception oppure una classe che deriva dalla classe Exception. L'istanza della classe Exception corrisponde all'errore verificatosi nel blocco Try.

Le proprietà dell'oggetto Exception consentono di identificare la causa e il percorso di un'eccezione. Ad esempio, nella proprietà StackTrace sono elencati i metodi chiamati che hanno causato l'eccezione, in modo da consentire di individuare il punto del codice in cui si è verificato l'errore. Tramite la proprietà Message viene restituito un messaggio in cui viene descritta l'eccezione. Tramite la proprietà HelpLink viene restituito un collegamento a un file della Guida associato. Tramite la proprietà InnerException viene restituito l'oggetto Exception mediante il quale è stata causata l'eccezione corrente oppure viene restituito Nothing se non è presente alcun oggetto Exception originale.

Considerazioni in caso di utilizzo di un blocco Try...Catch

Utilizzare un'istruzione Try…Catch solo segnalare il verificarsi di eventi anomali o imprevisti. Di seguito sono elencati alcuni dei motivi:

  • Il rilevamento di eccezioni in fase di esecuzione crea sovraccarico aggiuntivo e probabilmente risulta più lento rispetto a un controllo preventivo per evitare le eccezioni.

  • Se un blocco Catch non viene gestito correttamente, l'eccezione potrebbe non essere segnalata correttamente agli utenti.

  • La gestione delle eccezioni rende più complesso un programma.

Non sempre è necessaria un'istruzione Try…Catch per controllare una condizione che è probabile si verifichi. Nell'esempio seguente viene verificata l'esistenza di un file prima di tentarne l'apertura. In tal modo, la necessità di rilevare un'eccezione generata dal metodo OpenText si riduce.

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

Assicurarsi che il codice nei blocchi Catch consenta di segnalare correttamente le eccezioni agli utenti, tramite l'accesso thread-safe o messaggi appropriati. In caso contrario, le eccezioni potrebbero rimanere sconosciute.

Metodi di Async

Se si contrassegna un metodo con il modificatore Async, è possibile utilizzare l'operatore Attendere nel metodo. Un'istruzione con l'operatore Await sospende l'esecuzione del metodo finché l'attività attesa non completi. l'attività rappresenta il lavoro in corso. Quando l'attività associata all'operatore Await completa, l'esecuzione riprende lo stesso metodo. Per ulteriori informazioni, vedere Flusso di controllo in programmi asincroni (C# e Visual Basic).

Un'attività restituita da un metodo di Async può terminare lo stato Faulted, indicando che ha terminato a causa di un'eccezione non gestita. Un'attività può inoltre possibile terminare in uno stato annullato, pertanto OperationCanceledException generato dall'espressione di attesa. Per rilevare qualsiasi tipo di eccezione, inserire l'espressione Await associata all'attività in un blocco Try e per rilevare l'eccezione nel blocco Catch. Un esempio è dato più avanti in questo argomento.

Un'attività può essere in uno stato di errore perché più eccezioni sono responsabili dell'errore. Ad esempio, un'attività potrebbe essere il risultato di una chiamata a Task.WhenAll. Quando si attendono tale attività, l'eccezione viene rilevata una sola delle eccezioni e non è possibile prevedere quale eccezione viene intercettata. Un esempio è dato più avanti in questo argomento.

Un'espressione Await non può trovarsi a un blocco Catch o del blocco Finally.

Iteratori

Una funzione iteratori o una funzione di accesso Get esegue un'iterazione personalizzata in una raccolta. Un iteratore utilizza un'istruzione Prestazioni per restituire ogni elemento della raccolta uno alla volta. Chiama una funzione iteratori utilizzando Istruzione For Each...Next (Visual Basic).

Un'istruzione Yield può essere in un blocco Try. Un blocco Try contenente un'istruzione Yield può contenere blocchi Catch e può presentare un blocco Finally. Vedere “blocco try la sezione in Visual Basic„ Iteratori (C# e Visual Basic) per un esempio.

Un'istruzione Yield non può trovarsi a un blocco Catch o un blocco Finally.

Se il corpo For Each (l'esterno della funzione iteratori) genera un'eccezione, un blocco Catch nella funzione iteratori non viene eseguito, ma un blocco Finally nella funzione di iteratore viene eseguito. Un blocco Catch in una funzione iteratori rilevate solo le eccezioni che si verificano nella funzione di iteratore.

Situazioni parzialmente attendibili

Nelle situazioni di attendibilità parziale, ad esempio un'applicazione ospitata in una condivisione di rete, la struttura Try...Catch...Finally non intercetta le eccezioni di sicurezza che si verificano prima che venga richiamato il metodo contenente la chiamata. Nell'esempio riportato di seguito, se l'istruzione viene inserita su una condivisione server ed eseguita da tale posizione, verrà generato l'errore "System.Security.SecurityException: Richiesta non riuscita". Per ulteriori informazioni sulle eccezioni di sicurezza, vedere la classe SecurityException.

Try
    Process.Start("https://www.microsoft.com")
Catch ex As Exception
    MsgBox("Can't load Web page" & vbCrLf & ex.Message)
End Try

In una situazione di attendibilità parziale di questo tipo, è necessario inserire l'istruzione Process.Start in un'istruzione Sub separata. La chiamata iniziale a Sub avrà esito negativo. In questo modo, l'istruzione Try...Catch potrà intercettarlo prima che venga avviato l'oggetto Sub contenente Process.Start e prodotta l'eccezione di sicurezza.

Esempio

Nell'esempio riportato di seguito viene illustrata 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.
        MessageBox.Show("end of Try block")
    Catch ex As Exception
        ' Show the exception's message.
        MessageBox.Show(ex.Message)

        ' Show the stack trace, which is a list of methods 
        ' that are currently executing.
        MessageBox.Show("Stack Trace: " & vbCrLf & ex.StackTrace)
    Finally 
        ' This line executes whether or not the exception occurs.
        MessageBox.Show("in Finally block")
    End Try 
End Sub

Nell'esempio seguente, tramite il metodo CreateException viene generata un'eccezione NullReferenceException. Il codice tramite il quale viene generata l'eccezione non è in un blocco Try. Pertanto, il metodo CreateException non consente la gestione dell'eccezione. L'eccezione viene gestita tramite il metodo RunSample poiché la chiamata al metodo CreateException è in un blocco Try.

Nell'esempio vengono incluse le istruzioni Catch per diversi 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
        MessageBox.Show("NullReferenceException: " & ex.Message)
        MessageBox.Show("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

Nell'esempio seguente viene mostrato come utilizzare un'istruzione Catch When per filtrare un'espressione condizionale. Se l'espressione condizionale restituisce True, viene eseguito il codice nel blocco Catch.

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

Nell'esempio seguente è presente un'istruzione Try…Catch contenuta in un blocco Try. Tramite il blocco Catch interno viene generata un'eccezione la cui proprietà InnerException è impostata sull'eccezione originale. Tramite il blocco Catch esterno vengono segnalate l'eccezione propria del blocco e quella 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

Il seguente esempio viene illustrata la gestione delle eccezioni per i metodi async. Per intercettare un'eccezione che si applica a un'attività async, l'espressione Await è in un blocco Try del chiamante e l'eccezione viene rilevata nel blocco Catch.

Rimuovere il commento dalla riga Throw New Exception nell'esempio per illustrare la gestione delle eccezioni. L'eccezione viene rilevata nel blocco Catch, la proprietà IsFaulted dell'attività è impostata su Truee la proprietà Exception.InnerException dell'attività viene impostata sull'eccezione.

Rimuovere il commento dalla riga Throw New OperationCancelledException per illustrare ciò che si verifica quando si annulla un processo asincrono. L'eccezione viene rilevata nel blocco Catch e la proprietà IsCanceled dell'attività è impostata su True. Tuttavia, in alcuni casi non si applicano a questo esempio, IsFaulted è impostato su True e IsCanceled è 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

Il seguente esempio viene illustrata la gestione delle eccezioni in cui più attività possono comportare più eccezioni. Il blocco Try è l'espressione Await per l'attività che Task.WhenAll restituito. L'attività è completa quando le tre attività a cui si applica Task.WhenAll sono state completate.

Ciascuna delle cause di attività un'eccezione. Il blocco Catch scorre le eccezioni, che si trovano nella proprietà Exception.InnerExceptions dell'attività che Task.WhenAll restituito.

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

Vedere anche

Riferimenti

Err

Istruzione Exit (Visual Basic)

Istruzione On Error (Visual Basic)

Exception

Istruzione Throw (Visual Basic)

Concetti

Procedure consigliate per l'utilizzo dei frammenti di codice

Gestione delle eccezioni (Task Parallel Library)