Blocul catch și filtrele de excepții
Definirea blocului catch
Tratamentul excepțiilor este responsabilitatea blocului catch, care poate avea următoarele forme:
catch
{
// instrucțiuni executate
}
Acest bloc tratează orice excepție care apare în blocul try. Mai sus a fost demonstrat un exemplu al unui astfel de bloc.
catch (tip_excepție)
{
// instrucțiuni executate
}
Acest bloc tratează doar excepțiile care corespund tipului specificat în paranteze după operatorul catch.
De exemplu, să tratăm doar excepțiile de tip DivideByZeroException:
try
{
int x = 5;
int y = x / 0;
Console.WriteLine($"Rezultatul: {y}");
}
catch (DivideByZeroException)
{
Console.WriteLine("A apărut o excepție DivideByZeroException");
}
Cu toate acestea, dacă în blocul try apar excepții de alte tipuri decât DivideByZeroException, acestea nu vor fi tratate.
catch (tip_excepție nume_variabilă)
{
// instrucțiuni executate
}
Acest bloc tratează doar excepțiile care corespund tipului specificat în paranteze după operatorul catch, iar toată informația despre excepție este plasată într-o variabilă de acest tip. De exemplu:
try
{
int x = 5;
int y = x / 0;
Console.WriteLine($"Rezultatul: {y}");
}
catch (DivideByZeroException ex)
{
Console.WriteLine($"A apărut o excepție: {ex.Message}");
}
Acest caz este similar cu cel precedent, cu excepția faptului că aici se folosește o variabilă. În acest caz, informațiile despre excepția apărută sunt plasate în variabila ex, care reprezintă tipul DivideByZeroException. Cu ajutorul proprietății Message putem obține mesajul de eroare.
Dacă nu avem nevoie de informații despre excepție, putem să nu folosim variabila, ca în cazul precedent.
Filtrele de excepții
Filtrele de excepții permit tratarea excepțiilor în funcție de anumite condiții. Pentru a le aplica, după expresia catch urmează expresia when, după care în paranteze se specifică condiția:
catch when(condiție)
{
// instrucțiuni executate
}
În acest caz, tratarea excepției în blocul catch are loc doar dacă condiția din expresia when este adevărată. De exemplu:
int x = 1;
int y = 0;
try
{
int result1 = x / y;
int result2 = y / x;
}
catch (DivideByZeroException) when (y == 0)
{
Console.WriteLine("y nu trebuie să fie egal cu 0");
}
catch (DivideByZeroException ex)
{
Console.WriteLine(ex.Message);
}
În acest caz va fi aruncată o excepție, deoarece y=0. Aici avem două blocuri catch, ambele tratând excepții de tip DivideByZeroException, adică toate excepțiile generate la împărțirea la zero.
Dar, deoarece pentru primul bloc este specificată condiția y == 0, acest bloc va trata excepția - condiția specificată după operatorul when returnează true.
Situația opusă:
int x = 0;
int y = 1;
try
{
int result1 = x / y;
int result2 = y / x;
}
catch (DivideByZeroException) when (y == 0)
{
Console.WriteLine("y nu trebuie să fie egal cu 0");
}
catch (DivideByZeroException ex)
{
Console.WriteLine(ex.Message);
}
În acest caz va fi aruncată o excepție, deoarece x=0. Condiția primului bloc catch - y == 0 - acum returnează false. Prin urmare, CLR va continua să caute blocuri catch corespunzătoare și va alege pentru tratarea excepției al doilea bloc catch. În final, dacă eliminăm al doilea bloc catch, excepția nu va fi tratată deloc.