44 votes

Pourquoi l’ordre d’exécution de "infini" et "quand" est-il interverti dans C # 6.0?

J'ai vu cet exemple:

static void Main(string[] args)
{
    Console.WriteLine("Start");
    try
    {
        SomeOperation();
    }
    catch (Exception) when (EvaluatesTo())
    {
        Console.WriteLine("Catch");
    }
    finally
    {
        Console.WriteLine("Outer Finally");
    }
}

private static bool EvaluatesTo()
{
    Console.WriteLine($"EvaluatesTo: {Flag}");
    return true;
}

private static void SomeOperation()
{
    try
    {
        Flag = true;
        throw new Exception("Boom");
    }
    finally
    {
        Flag = false;
        Console.WriteLine("Inner Finally");
    }
}

Qui produit la sortie suivante:

Start
EvaluatesTo: True
Inner Finally
Catch
Outer Finally

Cela semble bizarre pour moi, et je suis à la recherche d'une bonne explication de cet ordre pour l'envelopper dans ma tête. Je m'attendais à de la finally bloc doit être exécutée avant d' when:

Start
Inner Finally
EvaluatesTo: True
Catch
Outer Finally

La documentation indique que ce ordre d'exécution est correcte, mais il ne précise pas pourquoi c'est fait comme ça et quelles sont exactement les règles de l'exécution de l'ordre ici.

38voto

Luaan Points 8934

Vous pourriez avoir été enseigné que, lorsque exception se produit, chaque méthode est considérée séparément. C'est, depuis l'intérieur de votre méthode a un try...finally, une exception sera la première à déclencher l' finally, et puis il va "chercher" pour un try plus haut. Ce n'est pas vrai.

À partir de la spécification ECMA de la CLR (ECMA-335, I. 12.4.2.5 vue d'ensemble de la gestion des exceptions):

Lorsqu'une exception se produit, la CLI de recherche le tableau pour la première protégé bloc

  • Protège une région, y compris le pointeur d'instruction en cours et
  • Est un gestionnaire catch block et
  • Dont le filtre souhaite gérer l'exception

Si aucune correspondance n'est trouvée dans la méthode actuelle, la méthode d'appel est recherché, et ainsi de suite. Si aucune correspondance n'est trouvée, la CLI dump une trace de la pile et abandonner le programme.

Si une correspondance est trouvée, la CLI de marcher sur la pile de retour vers le point situé juste, mais cette fois, l'appel de la enfin et gestionnaires d'erreur. Il commence alors le correspondant gestionnaire d'exception.

Comme vous pouvez le voir, le comportement est 100% compatible avec la spécification.

  1. Recherchez un protégé bloc - try en SomeOperation
  2. A-t-elle d'un gestionnaire catch block? Pas de.
  3. Recherchez un bloc protégé dans l'appel de la méthode - try en Main
  4. A-t-elle d'un gestionnaire catch block? Oui!
  5. Le filtre souhaitez gérer l'exception? Le filtre est évalué (avertissement: cela ne signifie pas que tous les filtres dans les protégés de bloc seront toujours évaluées - pas de problème si le filtre n'a pas d'effets secondaires, il ne faut pas, bien sûr), et le résultat est oui.
  6. Parcourir la pile de retour et d'exécuter tous enfin et gestionnaires d'erreur
    1. finally en SomeOperation

L' finally en Main n'est pas partie, bien sûr - il s'exécute lors de l'exécution de feuilles protégées bloc, indépendamment de l'exception.

EDIT:

Juste pour être complet, - il en a toujours été ainsi. La seule chose qui a changé est que C# supporte maintenant les filtres d'exception, qui vous permet d'observer l'ordre d'exécution. VB.NET pris en charge filtres d'exception à partir de la version 1.

-5voto

Thennarasan Points 604

Un bloc finally est toujours exécuté, qu'une exception soit levée ou non.

Un bloc finally exécute soit:

  • Après un bloc rattrapé termine
  • Après que le contrôle ait quitté le bloc try en raison d'une instruction jump (par exemple, return ou goto)
  • Après le bloc d'essai se termine

Les seules choses qui peuvent vaincre un bloc final sont une boucle infinie ou un processus qui envoie de manière abrupte. Un bloc finally aide à ajouter du déterminisme à un programme

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X