web-dev-qa-db-fra.com

Reprise de l'exécution du code après qu'une exception est levée et interceptée

Comment est-il possible de reprendre l'exécution de code après qu'une exception est levée?

Par exemple, prenez le code suivant:

namespace ConsoleApplication1
{
    public class Test
    {
        public void s()
        {
            throw new NotSupportedException();
            string @class = "" ;
            Console.WriteLine(@class);
            Console.ReadLine();
        }
    }

    public class Program
    {
        public static void Main(string[] args)
        {
            try
            {
                new Test().s();
            }
            catch (ArgumentException x)
            {
            }
            catch (Exception ex)
            {
            }
        }
    }
}

Après avoir détecté l'exception lors de la progression, le programme s'arrête. Comment continuer l'exécution?

EDIT: Ce que je veux dire spécifiquement, c'est la ligne Console.WriteLine (@class); ne semble pas être touché, car lorsque je l'exécute en mode débogage, le programme quitte le mode débogage. Je veux courir vers cette ligne et m'y arrêter.

Merci

28
GurdeepS

Eh bien, vous n'avez pas de code après les blocs catch, donc le programme cesserait de fonctionner. Je ne sais pas ce que vous essayez de faire.

Ce qui suit devrait être la preuve que le programme ne s'arrête pas simplement après les blocs catch. Il exécutera le code après les blocs catch s'il y a du code à exécuter:

static void Main(string[] args)
{
    try
    {
        new Test().s();
    }
    catch (ArgumentException x)
    {
        Console.WriteLine("ArgumentException caught!");
    }
    catch (Exception ex) 
    { 
        Console.WriteLine("Exception caught!");
    }

    Console.WriteLine("I am some code that's running after the exception!");
}

Le code affichera la chaîne appropriée en fonction de l'exception qui a été interceptée. Ensuite, il imprimera I am some code that's running after the exception! À la fin.

MISE À JOUR

Dans votre montage, vous avez demandé pourquoi Console.WriteLine(@class); ne semble pas être touché. La raison en est que vous lisez explicitement une exception dans la toute première ligne de votre méthode s(); tout ce qui suit est ignoré. Lorsqu'une exception est rencontrée, l'exécution s'arrête et l'exception est propagée dans la pile d'appels jusqu'à ce que le gestionnaire approprié puisse la gérer (il peut s'agir d'un bloc catch qui correspond au try qui enveloppe l'instruction) en question dans la même méthode, ou il peut s'agir d'un bloc catch plus haut dans la pile des appels. Si aucun gestionnaire approprié n'est trouvé, le programme se terminera par une trace de pile [au moins dans Java - je ne sais pas si la même chose se produit en C #]).

Si vous voulez frapper la ligne Console.WriteLine, Alors vous ne devriez pas lancer explicitement une exception au début de la méthode.

33
Vivin Paliath

Il semble que vous souhaitiez des exceptions pouvant être reprises. C # ne fait pas d'exceptions pouvant être reprises, et je doute que CLR les supporte.

Le but de lever une exception est d'annuler une fonction et une opération entière (pile d'appels) si/quand quelque chose dans l'environnement d'appel (paramètres, état d'objet, état global) rend l'opération de la fonction impossible ou invalide. Passer un paramètre zéro à une fonction qui doit diviser une quantité par ce paramètre, par exemple. La division par zéro ne produira pas de résultat significatif, et si c'est le seul but de la fonction, alors la fonction ne peut pas retourner un résultat significatif non plus. Alors, jetez une exception. Cela provoquera l'exécution pour sauter à la capture la plus proche ou enfin bloquer sur la pile d'appels. Il n'y a pas de retour à la fonction qui a levé l'exception.

Si vous souhaitez entrer dans votre code dans le débogueur pour tracer les appels Console.WriteLine (), vous devez supprimer la nouvelle ligne Throw NotSupportedException () de votre code et recompiler.

10
dthorpe

Si vous craignez qu'une exception soit levée dans la méthode mais que vous souhaitez que la méthode continue, ajoutez un gestionnaire d'erreurs à l'intérieur de la méthode.

class Test 
{ 
    public void s() 
    { 
        try
          {
              // Code that may throw an exception
              throw new NotSupportedException();
          } 
          catch(Exception ex)
          {
              // Handle the exception - log?, reset some values?
          }
          string @class = "" ; 
          Console.WriteLine(@class); 
          Console.ReadLine(); 
    } 
} 

Vous pouvez également retourner un booléen ou une autre valeur pour indiquer l'état.

8
Patrick

Avertissement: je ne suggère pas que vous le fassiez réellement.

Vous pouvez imiter l'ancien style VB On On Resume Next avec le code suivant.

public static class ControlFlow
{
  public static Exception ResumeOnError(Action action)
  {
    try
    {
      action();
      return null;
    }
    catch (Exception caught)
    { 
      return caught;
    }
  }
}

Et puis il pourrait être utilisé comme suit.

public static void Main()
{
  ControlFlow.ResumeOnError(() => { throw new NotSupportedException(); });
  ControlFlow.ResumeOnError(() => { Console.WriteLine(); });
  ControlFlow.ResumeOnError(() => { Console.ReadLine(); });
}
3
Brian Gideon

Un code simple que j'ai mis en place pour intercepter les exceptions qui sont lancées dans un bloc catch:

try
{
    //do code here
}
catch (Exception ex)
{
    try { SomeMethod1(); }
    catch { }

    try { SomeMethod2(); }
    catch { }

    try { SomeMethod3(); }
    catch { }
}
finally
{
    //cleanup goes here
}
1
oscilatingcretin

L'exécution se poursuit mais il n'y a pas de code après que l'exception a été interceptée. Si vous souhaitez appeler plusieurs fois s, pensez à encapsuler le bloc try/catch dans une boucle while.

0
JB King

Le programme s'arrête car il n'y a pas de code suivant à exécuter dans la méthode Main ()! Vous pouvez ajouter la ligne suivante à votre code pour maintenir le programme en cours d'exécution jusqu'à ce qu'il y ait une entrée de console:

Console.ReadLine();
0
Marius Schulz

Pour ce code, vous ne pouvez pas. Si vous divisez les tâches en blocs plus petits, vous pouvez reprendre au bloc suivant. Mais normalement, il est plus facile d'avoir un mécanisme différent que les exceptions pour signaler les erreurs non fatales, comme une fonction de rappel qui renvoie s'il faut continuer ou non.

0
Pete Kirkham

Vous pouvez utiliser la fonctionnalité "step-over" dans le débogage pour y parvenir sur une base par exécution.

0
Matt Mitchell