try {
// Do stuff
}
catch (Exception e) {
throw;
}
finally {
// Clean up
}
Dans le bloc ci-dessus, quand le bloc finally est-il appelé? Avant le lancer de e ou est finalement appelé et ensuite attraper?
try {
// Do stuff
}
catch (Exception e) {
throw;
}
finally {
// Clean up
}
Dans le bloc ci-dessus, quand le bloc finally est-il appelé? Avant le lancer de e ou est finalement appelé et ensuite attraper?
Réponses:
Il serait appelé après que e soit relancé (c'est-à-dire après l'exécution du bloc catch)
éditer cela 7 ans plus tard - une note importante est que s'il e
n'est pas intercepté par un bloc try / catch plus haut dans la pile d'appels ou géré par un gestionnaire d'exceptions global, alors le finally
bloc peut ne jamais s'exécuter du tout.
finally
est pas exécuté si l'exception levée dans le précédent catch
est jamais pris dans un extérieur try
- catch
bloc!
Pourquoi ne pas l'essayer:
outer try
inner try
inner catch
inner finally
outer catch
outer finally
avec code (formaté pour un 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");
}
}
outer try
inner try
inner catch
Unhandled Exception: System.DivideByZeroException...
Après avoir lu toutes les réponses ici, il semble que la réponse finale est que cela dépend :
Si vous relancez une exception dans le bloc catch et que l'exception est interceptée à l'intérieur d'un autre bloc catch, tout s'exécute selon la documentation.
Cependant, si l'exception re-trown n'est pas gérée, le paramètre finally ne s'exécute jamais.
J'ai testé cet exemple de code dans VS2010 avec 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:
--outer try
---- inner try
---- inner catch
----
inside enfin --outer catch
--outer enfin
Huzzah!Exemple 2: relancez en dehors d'un autre bloc try:
--try
--catchException non gérée: System.Exception: une exception de type «System.Exception» a été levée.
à ConsoleApplication1.Program.Main () dans C: \ source locale \ ConsoleApplication1 \ Program.cs: ligne 53
Votre exemple se comporterait de la même manière que ce code:
try {
try {
// Do stuff
} catch(Exception e) {
throw e;
}
} finally {
// Clean up
}
Comme une note de côté, si vous avez vraiment moyen throw e;
, il est (qui est, jetez la même exception que vous venez de prendre) beaucoup mieux pour le faire throw;
, car cela préservera la trace de la pile d' origine au lieu de créer un nouveau.
finally
bloc fonctionnera en fait après le catch
bloc (même si le bloc catch relance l'exception), ce que mon extrait de code tente d'illustrer.
try
bloc de cela ma réponse a un "try-catch". J'essaie d'expliquer le comportement de la construction en 3 parties en utilisant deux constructions en 2 parties. Je ne vois aucun signe de deuxième try
blocage dans la question initiale, donc je ne comprends pas d'où vous venez.
S'il y a une exception non gérée dans un bloc catch handler, le bloc finally est appelé exactement zéro fois
static void Main(string[] 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");
}
}
Production:
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. à TestExceptionNesting.Program.Main (String [] 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 interview et l'intervieweur a continué à revenir "êtes-vous sûr que finalement ne sera pas appelé?" Je ne savais pas s'il s'agissait d'une question piège ou si l'intervieweur avait autre chose en tête et a écrit le mauvais code à déboguer, alors je suis rentré à la maison et l'ai essayé (construire et exécuter, pas d'interaction avec le débogueur), juste pour me mettre à l'esprit du repos.
Test avec une application console C #, le code finally a été exécuté après la levée de l'exception: La "boîte de dialogue d'erreur d'application" existait et après avoir choisi l'option "Fermer le programme", le bloc finally a été exécuté dans cette fenêtre de console. Mais en définissant le point de rupture à l'intérieur du bloc de code finally, je ne peux jamais l'atteindre. Le débogueur continue de s'arrêter à l'instruction throw. Voici mon code de test:
class Program
{
static void Main(string[] args)
{
string msg;
Console.WriteLine(string.Format("GetRandomNuber returned: {0}{1}", GetRandomNumber(out msg), msg) == "" ? "" : "An error has occurred: " + msg);
}
static int GetRandomNumber(out string 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