try-catch (Riferimenti per C#)
Aggiornamento: novembre 2007
L'istruzione try-catch è costituita da un blocco try seguito da una o più clausole catch che specificano gestori per diverse eccezioni. Quando viene generata un'eccezione, Common Language Runtime (CLR) cerca l'istruzione catch che gestisce l'eccezione indicata. Se il metodo in esecuzione non contiene tale blocco catch, CLR analizza il metodo che ha chiamato il metodo corrente e così via lungo lo stack di chiamate. Se non viene trovato alcun blocco catch, CLR visualizza un messaggio di eccezione non gestita all'utente e interrompe l'esecuzione del programma.
Il blocco try contiene il codice controllato che può generare l'eccezione. Il blocco viene eseguito fino a quando non viene generata un'eccezione o fino al corretto completamento dell'esecuzione. Ad esempio, il tentativo riportato di seguito di eseguire il cast di un oggetto null genera l'eccezione NullReferenceException:
object o2 = null;
try
{
int i2 = (int)o2; // Error
}
Anche se la clausola catch può essere utilizzata senza argomenti per rilevare qualsiasi tipo di eccezione, questo utilizzo non viene consigliato. In generale, è opportuno rilevare solo le eccezioni per le quali si conosce la modalità di recupero. Pertanto, è consigliabile specificare sempre un argomento oggetto derivato da System.Exception, ad esempio:
catch (InvalidCastException e)
{
}
È possibile utilizzare più di una clausola catch specifica nella stessa istruzione try-catch. In questo caso, l'ordine delle clausole catch è importante poiché le clausole catch vengono esaminate nell'ordine specificato. Vengono intercettate prima le eccezioni più specifiche, quindi quelle meno specifiche. Il compilatore produrrà un errore se si ordinano i blocchi catch in modo tale da non raggiungere mai un blocco successivo.
Un'istruzione throw può essere utilizzata nel blocco catch per rigenerare l'eccezione che è stata intercettata dall'istruzione catch. Di seguito è riportato un esempio:
catch (InvalidCastException e)
{
throw (e); // Rethrowing exception e
}
È possibile anche generare una nuova eccezione. Quando si esegue questa operazione, specificare l'eccezione da rilevare come eccezione interna:
catch (InvalidCastException e)
{
// Can do cleanup work here.
throw new CustomException("Error message here.", e);
}
Se si desidera rigenerare l'eccezione correntemente gestita da una clausola catch senza parametri, utilizzare l'istruzione throw senza argomenti. Di seguito è riportato un esempio:
catch
{
throw;
}
All'interno di un blocco try inizializzare solo le variabili dichiarate in questo ambito; in caso contrario può verificarsi un'eccezione prima del completamento dell'esecuzione del blocco. Nell'esempio di codice riportato di seguito la variabile x viene inizializzata all'interno del blocco try. Un tentativo di utilizzare questa variabile all'esterno del blocco try nell'istruzione Write(x) genererà l'errore del compilatore: Utilizzo della variabile locale non assegnata.
static void Main()
{
int x;
try
{
// Don't initialize this variable here.
x = 123;
}
catch
{
}
// Error: Use of unassigned local variable 'x'.
Console.Write(x);
}
Per ulteriori informazioni sulla clausola catch, vedere try-catch-finally.
Esempio
Nell'esempio seguente il blocco try contiene una chiamata al metodo ProcessString che potrebbe causare un'eccezione. La clausola catch contiene il gestore eccezioni che consente semplicemente di visualizzare un messaggio sullo schermo. Quando l'istruzione throw viene chiamata dall'interno di MyMethod, il sistema cerca l'istruzione catch e visualizza il messaggio Exception caught.
class TryFinallyTest
{
static void ProcessString(string s)
{
if (s == null)
{
throw new ArgumentNullException();
}
}
static void Main()
{
string s = null; // For demonstration purposes.
try
{
ProcessString(s);
}
catch (Exception e)
{
Console.WriteLine("{0} Exception caught.", e);
}
}
}
/*
Output:
System.ArgumentNullException: Value cannot be null.
at TryFinallyTest.Main() Exception caught.
* */
In questo esempio vengono utilizzate due istruzioni catch. Viene intercettata l'eccezione più specifica, che è la prima nell'ordine.
class ThrowTest3
{
static void ProcessString(string s)
{
if (s == null)
{
throw new ArgumentNullException();
}
}
static void Main()
{
try
{
string s = null;
ProcessString(s);
}
// Most specific:
catch (ArgumentNullException e)
{
Console.WriteLine("{0} First exception caught.", e);
}
// Least specific:
catch (Exception e)
{
Console.WriteLine("{0} Second exception caught.", e);
}
}
}
/*
Output:
System.ArgumentNullException: Value cannot be null.
at TryFinallyTest.Main() First exception caught.
*/
Nell'esempio precedente, se si inizia con la clausola catch meno specifica, verrà generato il seguente messaggio di errore:
A previous catch clause already catches all exceptions of this or a super type ('System.Exception')
Per rilevare l'eccezione meno specifica, è necessario sostituire l'istruzione throw con l'istruzione seguente:
throw new Exception();
Specifiche del linguaggio C#
Per ulteriori informazioni, vedere le sezioni riportate di seguito in Specifiche del linguaggio C#:
5.3.3.13 Istruzioni try-catch
8.10 Istruzione try
16 Eccezioni
Vedere anche
Attività
Procedura: generare eccezioni in modo esplicito
Concetti
Riferimenti
The try, catch, and throw Statements
Istruzioni di gestione delle eccezioni (Riferimenti per C#)
try-finally (Riferimenti per C#)