Quand est enfin exécuté si vous lancez une exception à partir du bloc catch?

try { // Do stuff } catch (Exception e) { throw; } finally { // Clean up } 

Dans le bloc ci-dessus, quand le bloc finally est-il appelé? Avant le lancement de e ou est finalement appelé et ensuite attraper?

Il serait appelé après que e soit renvoyé (c’est-à-dire après l’exécution du bloc catch)

éditer ceci 7 ans plus tard – une note importante est que si e n’est pas attrapé par un bloc try / catch plus haut dans la stack d’appels ou géré par un gestionnaire d’exceptions global, alors le bloc finally peut ne jamais s’exécuter du tout.

Pourquoi ne pas l’essayer:

 outer try inner try inner catch inner finally outer catch outer finally 

avec code (formaté pour l’espace vertical):

 static void Main() { try { Console.WriteLine("outer try"); DoIt(); } catch { Console.WriteLine("outer catch"); // swallow } finally { Console.WriteLine("outer finally"); } } static void DoIt() { try { Console.WriteLine("inner try"); int i = 0; Console.WriteLine(12 / i); // oops } catch (Exception e) { Console.WriteLine("inner catch"); throw e; // or "throw", or "throw anything" } finally { Console.WriteLine("inner finally"); } } 

Après avoir lu toutes les réponses, il semble que la réponse finale dépend de :

  • Si vous relancez une exception dans le bloc catch et que cette exception est interceptée dans un autre bloc catch, tout s’exécute conformément à la documentation.

  • Cependant, si l’exception de reprise est non gérée, le finalement ne s’exécute jamais.

J’ai testé cet exemple de code dans VS2010 w / C # 4.0

 static void Main() { Console.WriteLine("Example 1: re-throw inside of another try block:"); try { Console.WriteLine("--outer try"); try { Console.WriteLine("----inner try"); throw new Exception(); } catch { Console.WriteLine("----inner catch"); throw; } finally { Console.WriteLine("----inner finally"); } } catch { Console.WriteLine("--outer catch"); // swallow } finally { Console.WriteLine("--outer finally"); } Console.WriteLine("Huzzah!"); Console.WriteLine(); Console.WriteLine("Example 2: re-throw outside of another try block:"); try { Console.WriteLine("--try"); throw new Exception(); } catch { Console.WriteLine("--catch"); throw; } finally { Console.WriteLine("--finally"); } Console.ReadLine(); } 

Voici la sortie:

Exemple 1: relancez à l’intérieur d’un autre bloc try:
–out essayer
—- intérieur essayer
—- prise intérieure
—- intérieur finalement
–outout
–out enfin
Huzzah!

Exemple 2: relancez en dehors d’un autre bloc try:
–essayer
–capture

Exception non gérée: System.Exception: Une exception de type ‘System.Exception’ a été levée.
at ConsoleApplication1.Program.Main () dans C: \ source locale \ ConsoleApplication1 \ Program.cs: ligne 53

Votre exemple se comporterait de manière identique à ce code:

 try { try { // Do stuff } catch(Exception e) { throw e; } } finally { // Clean up } 

En guise de note, si vous voulez vraiment dire throw e; (c’est-à-dire, jetez la même exception que vous venez de capturer), il est préférable de simplement throw; , car cela préservera la trace de la stack d’origine au lieu d’en créer une nouvelle.

S’il y a une exception non gérée dans un bloc de gestionnaire catch, le bloc finally est appelé exactement zéro fois

  static void Main(ssortingng[] args) { try { Console.WriteLine("in the try"); int d = 0; int k = 0 / d; } catch (Exception e) { Console.WriteLine("in the catch"); throw; } finally { Console.WriteLine("In the finally"); } } 

Sortie:

C: \ users \ administrator \ documents \ TestExceptionNesting \ bin \ Release> TestExceptionNesting.exe

dans l’essai

dans la prise

Exception non gérée: System.DivideByZeroException: Tentative de division par zéro. at TestExceptionNesting.Program.Main (Ssortingng [] args) dans C: \ users \ administrator \ documents \ TestExceptionNesting \ TestExceptionNesting.cs: ligne 22

C: \ users \ administrator \ documents \ TestExceptionNesting \ bin \ release>

On m’a posé cette question aujourd’hui lors d’une entrevue et l’intervieweur a continué à revenir “êtes-vous sûr que le dernier ne soit pas appelé?” J’étais incertain si cela signifiait une question piège ou l’intervieweur avait autre chose en tête et a écrit le mauvais code pour que je puisse le déboguer, alors je suis rentré et j’ai essayé (construire et exécuter, pas d’interaction avec le débogueur) du repos.

Un moyen simple de dire aussi est de déboguer votre code et de noter quand il est enfin appelé.

En testant avec une application console C #, le code final a été exécuté après la levée de l’exception: le “dialog d’erreur de l’application” existait et après avoir choisi l’option “Fermer le programme”, le bloc finally était exécuté dans cette fenêtre. Mais en définissant le sharepoint rupture dans le bloc de code finally, je ne peux jamais le bash. Le débogueur s’arrête à l’instruction throw. Voici mon code de test:

  class Program { static void Main(ssortingng[] args) { ssortingng msg; Console.WriteLine(ssortingng.Format("GetRandomNuber returned: {0}{1}", GetRandomNumber(out msg), msg) == "" ? "" : "An error has occurred: " + msg); } static int GetRandomNumber(out ssortingng errorMessage) { int result = 0; try { errorMessage = ""; int test = 0; result = 3/test; return result; } catch (Exception ex) { errorMessage = ex.Message; throw ex; } finally { Console.WriteLine("finally block!"); } } } 

Débogage dans VS2010 – .NET Framework 4.0