Un'eccezione è un comportamento indesiderato e non previsto, che fa andare in errore un programma. Un classico esempio è data da un tentativo di divisione per zero, ma potrebbe anche essere una conversione esplicita de una stringa ad un intero.
Senza la gestione delle eccezioni, quando un programma esegue un'istruzione che porta ad un errore a runtime, viene interrotta e viene mostrato un messaggio di errore.
Per evitare ciò possiamo utilizzare la gestione delle eccezioni.
Possiamo includere il blocco di codice che pensiamo possa portare ad un'eccezione, in un blocco try catch finally
Esempio
Consideriamo il seguente codice
using System; namespace Sample
{ public class Sample
{ public static void Main()
{ int munero = 10; int divisore = 0; int risultato = 0;
risultato = (munero / divisore);
Console.WriteLine("Fine elaborazione");
}
}
}
Da come output:
Unhandled Exception: System.DivideByZeroException: Attempted to divide by zero. at Sample.Sample.Main() in c:\documents and settings\scuderi\my documents\visual studio project\\consoleapplication1\class1.cs:line 12
e termina l'esecuzione anche se c'era dell'altro codice da eseguire.
try catch finally
Vediamo con la gestione delle eccezioni
using System; namespace Sample
{ public class Sample
{ public static void Main()
{ int numero = 10; int divisore = 0; int risultato = 0; try
{
risultato = (numero / divisore);
} catch (System.DivideByZeroException e)
{
Console.WriteLine("Errore: " + e.Message);
} finally
{
Console.WriteLine("Fine elaborazione");
}
}
}
}
Oputut:
Errore: Attempted to divide by zero.
Fine elaborazione
La divisione per zero "solleva" un'eccezione, che viene "gestita" nel blocco catch
In più il programma continua l'esecuzione ed il blocco finally viene eseguito.
Da notare che il codice nel blocco finally, viene eseguito comunque, è utile quindi per far eseguire al sistema operazioni di pulizia come la chiusura di recordset o di connessioni a database, perchè siamo sicuri che verranno eseguite.
Eccezioni, gestirle o propagarle? throw
Quando abbiamo una eccezione all'interno di un metodo, possiamo decidere se gestirla localmente oppure se propagarla al chiamante.
Questo può essere utile se vogliamo gestire tutte le eccezioni in un blocco di codice e non per singola funzione.
Vediamo un esempio.
using System; namespace Sample
{ public class Sample
{ public static void Main()
{ string strNumero = ""; int numero = 0; int divisore = 0; int risultato = 0; try
{ //leggo il numero
Console.Write("Numero: ");
strNumero = Console.ReadLine();
numero = converti(strNumero); //leggo il divisore
Console.Write("Divisore: ");
strNumero = Console.ReadLine();
divisore = converti(strNumero); //calcolo il risultato
risultato = dividi(numero, divisore);
Console.WriteLine("Risultato: " + risultato);
} catch (Exception ex)
{ if (ex.Message =="Conversione")
Console.WriteLine("Errore di conversione"); if (ex.Message =="Divisione")
Console.WriteLine("Divisione per zero");
}
}
private static int converti(string strNumero)
{ try
{ return Convert.ToInt32(strNumero);
} catch
{ throw new Exception("Conversione");
}
}
private static int dividi(int numero, int divisore)
{ try
{ return (numero / divisore);
} catch
{ throw new Exception("Divisione");
}
}
}
}
vediamo cosa succede:
Prima esecuzione
Numero: 4
Divisore: 2
Risultato: 2
Seconda esecuzione
Numero: 4
Divisore: e
Errore di conversione
Terza esecuzione
Numero: 4
Divisore: 0
Divisione per zero
L'eccezione viene sollevata nel metodo chiamato, ma poi viene propagata e estita nel Main.