MySQL Java JavaScript PHP Python HTML-CSS C-sharp

Căutarea blocului catch la tratarea excepțiilor

Dacă codul care declanșează o excepție nu este plasat într-un bloc try sau este plasat într-o construcție try..catch care nu conține un bloc catch corespunzător pentru tratarea excepției apărute, sistemul va căuta un handler de excepție corespunzător în stiva de apeluri.

De exemplu, să considerăm următorul program:

try
{
   TestClass.Method1();
}
catch (DivideByZeroException ex)
{
   Console.WriteLine($"Catch în Main : {ex.Message}");
}
finally
{
   Console.WriteLine("Bloc finally în Main");
}
Console.WriteLine("Sfârșitul metodei Main");

class TestClass
{
   public static void Method1()
   {
       try
       {
           Method2();
       }
       catch (IndexOutOfRangeException ex)
       {
           Console.WriteLine($"Catch în Method1 : {ex.Message}");
       }
       finally
       {
           Console.WriteLine("Bloc finally în Method1");
       }
       Console.WriteLine("Sfârșitul metodei Method1");
   }
   static void Method2()
   {
       try
       {
           int x = 8;
           int y = x / 0;
       }
       finally
       {
           Console.WriteLine("Bloc finally în Method2");
       }
       Console.WriteLine("Sfârșitul metodei Method2");
   }
}

În acest caz, stiva de apeluri arată astfel: metoda Main apelează metoda Method1, care la rândul său apelează metoda Method2. În metoda Method2 se generează o excepție de tip DivideByZeroException. Vizual, stiva de apeluri poate fi reprezentată astfel:

Ce se întâmplă în acest caz când se generează o excepție?

  • Metoda Main apelează metoda Method1, iar aceasta apelează metoda Method2, unde se generează excepția DivideByZeroException
  • Sistemul vede că codul care a generat excepția este plasat într-o construcție try..catch:
try
{
   int x = 8;
   int y = x / 0;
}
finally
{
   Console.WriteLine("Bloc finally în Method2");
}

Sistemul caută în această construcție un bloc catch care să trateze excepția DivideByZeroException. Cu toate acestea, nu există un astfel de bloc catch.

  • Sistemul coboară în stiva de apeluri în metoda Method1, care a apelat Method2. Aici, apelul Method2 este plasat într-o construcție try..catch:
try
{
   Method2();
}
catch (IndexOutOfRangeException ex)
{
   Console.WriteLine($"Catch în Method1 : {ex.Message}");
}
finally
{
   Console.WriteLine("Bloc finally în Method1");
}

Sistemul caută și aici un bloc catch care să trateze excepția DivideByZeroException, dar nu găsește unul.

  • Sistemul coboară mai departe în stiva de apeluri în metoda Main, care a apelat Method1. Aici, apelul Method1 este plasat într-o construcție try..catch:
try
{
   TestClass.Method1();
}
catch (DivideByZeroException ex)
{
   Console.WriteLine($"Catch în Main : {ex.Message}");
}
finally
{
   Console.WriteLine("Bloc finally în Main");
}

Sistemul găsește în această construcție un bloc catch care tratează excepția DivideByZeroException.

  • În cele din urmă, sistemul a găsit blocul catch corespunzător în metoda Main pentru a trata excepția apărută în metoda Method2 - adică în metoda inițială unde a apărut excepția. Dar acest bloc catch NU se execută imediat. Sistemul urcă înapoi pe stiva de apeluri în vârful metodei Method2 și execută blocul finally:
finally
{
   Console.WriteLine("Bloc finally în Method2");
}
  • Apoi, sistemul coboară în stiva de apeluri în metoda Method1 și execută blocul finally:
finally
{
   Console.WriteLine("Bloc finally în Method1");
}
  • Apoi, sistemul coboară în stiva de apeluri în metoda Main și execută blocul catch găsit și blocul finally următor:
catch (DivideByZeroException ex)
{
   Console.WriteLine($"Catch în Main : {ex.Message}");
}
finally
{
   Console.WriteLine("Bloc finally în Main");
}
  • După aceasta, se execută codul care urmează construcției try..catch în metoda Main:
Console.WriteLine("Sfârșitul metodei Main");

Este important de menționat că codul care urmează după construcția try..catch în metodele Method1 și Method2 nu se execută, deoarece handler-ul de excepții a fost găsit doar în metoda Main.

Output-ul în consolă al programului:

Bloc finally în Method2
Bloc finally în Method1
Catch în Main: Attempted to divide by zero
Bloc finally în Main
Sfârșitul metodei Main
← Lecția anterioară Lecția următoare →