MySQL Java JavaScript PHP Python HTML-CSS C-sharp

Tipuri de excepții. Clasa Exception

Clasa de bază pentru toate tipurile de excepții este clasa Exception. Această clasă definește o serie de proprietăți prin care se poate obține informații despre excepție.

  • InnerException: stochează informații despre excepția care a cauzat excepția curentă
  • Message: stochează mesajul despre excepție, textul erorii
  • Source: stochează numele obiectului sau al ansamblului care a cauzat excepția
  • StackTrace: returnează o reprezentare sub formă de șir a stivei de apeluri care au dus la apariția excepției
  • TargetSite: returnează metoda în care a fost generată excepția

De exemplu, să tratăm excepțiile de tip Exception:

try
{
   int x = 5;
   int y = x / 0;
   Console.WriteLine($"Rezultatul: {y}");
}
catch (Exception ex)
{
   Console.WriteLine($"Excepție: {ex.Message}");
   Console.WriteLine($"Metodă: {ex.TargetSite}");
   Console.WriteLine($"Trecere prin stivă: {ex.StackTrace}");
}

Cu toate acestea, deoarece tipul Exception este tipul de bază pentru toate excepțiile, expresia catch (Exception ex) va trata toate excepțiile care pot apărea.

Există și tipuri de excepții mai specializate, care sunt destinate tratării unor anumite tipuri de excepții. Acestea sunt destul de numeroase, dar iată câteva exemple:

  • DivideByZeroException: reprezintă excepția generată la împărțirea la zero
  • ArgumentOutOfRangeException: este generată atunci când valoarea unui argument este în afara intervalului valorilor acceptabile
  • ArgumentException: este generată atunci când o valoare incorectă este transmisă unui parametru al unei metode
  • IndexOutOfRangeException: este generată atunci când un index al unui element al unui array sau colecție este în afara intervalului valorilor acceptabile
  • InvalidCastException: este generată la încercarea de a face o conversie de tipuri nevalidă
  • NullReferenceException: este generată la încercarea de a accesa un obiect care este null (practic nedefinit)

În cazul necesității, putem diferenția tratarea diverselor tipuri de excepții, incluzând blocuri catch adiționale:

static void Main(string[] args)
{
   try
   {
       int[] numbers = new int[4];
       numbers[7] = 9;     // IndexOutOfRangeException

       int x = 5;
       int y = x / 0;  // DivideByZeroException
       Console.WriteLine($"Rezultatul: {y}");
   }
   catch (DivideByZeroException)
   {
       Console.WriteLine("A apărut o excepție DivideByZeroException");
   }
   catch (IndexOutOfRangeException ex)
   {
       Console.WriteLine(ex.Message);
   }
           
   Console.Read();
}

În acest caz, blocurile catch tratează excepțiile de tip IndexOutOfRangeException și DivideByZeroException. Când în blocul try apare o excepție, CLR va căuta blocul catch corespunzător pentru a trata excepția. Astfel, în acest caz, pe linia:

numbers[7] = 9;

are loc accesarea celui de-al 7-lea element al array-ului. Cu toate acestea, deoarece array-ul are doar 4 elemente, vom primi o excepție de tip IndexOutOfRangeException. CLR va găsi blocul catch care tratează această excepție și va transfera controlul acestuia.

Trebuie menționat că în acest caz în blocul try există o situație care generează o a doua excepție - împărțirea la zero.

Totuși, deoarece după generarea excepției IndexOutOfRangeException controlul este transferat către blocul catch corespunzător, împărțirea la zero int y = x / 0 nu va fi executată, prin urmare excepția de tip DivideByZeroException nu va fi niciodată generată.

Totuși, să considerăm o altă situație:

try
{
   object obj = "you";
   int num = (int)obj;     // System.InvalidCastException
   Console.WriteLine($"Rezultatul: {num}");
}
catch (DivideByZeroException)
{
   Console.WriteLine("A apărut o excepție DivideByZeroException");
}
catch (IndexOutOfRangeException)
{
   Console.WriteLine("A apărut o excepție IndexOutOfRangeException");
}

În acest caz, în blocul try este generată o excepție de tip InvalidCastException, dar nu există un bloc catch corespunzător pentru tratarea acestei excepții. Prin urmare, programul se va închide brusc.

De asemenea, putem defini un bloc catch specific pentru InvalidCastException, dar ideea este că teoretic în cod pot fi generate diverse tipuri de excepții.

Și nu are sens să definim blocuri catch pentru toate tipurile de excepții dacă tratarea excepțiilor este similară. În acest caz, putem defini un bloc catch pentru tipul de bază Exception:

try
{
   object obj = "you";
   int num = (int)obj;     // System.InvalidCastException
   Console.WriteLine($"Rezultatul: {num}");
}
catch (DivideByZeroException)
{
   Console.WriteLine("A apărut o excepție DivideByZeroException");
}
catch (IndexOutOfRangeException)
{
   Console.WriteLine("A apărut o excepție IndexOutOfRangeException");
}
catch (Exception ex)
{
   Console.WriteLine($"Excepție: {ex.Message}");
}

În acest caz, blocul catch (Exception ex){} va trata toate excepțiile, cu excepția celor de tip DivideByZeroException și IndexOutOfRangeException.

Blocurile catch pentru excepțiile mai generale, de bază, trebuie plasate la final - după blocurile catch pentru tipurile mai specifice de excepții. CLR va alege pentru tratarea excepției primul bloc catch care corespunde tipului de excepție generată.

Prin urmare, în acest caz, mai întâi sunt tratate excepțiile de tip DivideByZeroException și IndexOutOfRangeException, iar apoi cele de tip Exception (deoarece DivideByZeroException și IndexOutOfRangeException sunt derivate din clasa Exception).

← Lecția anterioară Lecția următoare →