Recherche…


Remarques

En relation:

Prendre une exception

Le code peut et doit prévoir des exceptions dans des circonstances exceptionnelles. Des exemples de ceci incluent:

L'appelant peut gérer ces exceptions en les "attrapant" et ne devrait le faire que lorsque:

  • Il peut en fait résoudre le cas exceptionnel ou se rétablir correctement;
  • Il peut fournir un contexte supplémentaire à l'exception qui serait utile si l'exception doit être renvoyée (les exceptions renvoyées sont interceptées par les gestionnaires d'exceptions en amont de la pile d'appels)

Il convient de noter que choisir de ne pas attraper une exception est parfaitement valable si l'intention est de le traiter à un niveau supérieur.

La capture d'une exception se fait en encapsulant le code potentiellement lançant dans un bloc try { ... } comme suit et en capturant les exceptions qu'il peut gérer dans un bloc catch (ExceptionType) { ... } :

Console.Write("Please enter a filename: ");
string filename = Console.ReadLine();

Stream fileStream;

try
{
    fileStream = File.Open(filename);
}
catch (FileNotFoundException)
{
    Console.WriteLine("File '{0}' could not be found.", filename);
}

Utiliser un bloc

Le bloc finally { ... } d'un try-finally ou de try-catch-finally s'exécutera toujours, qu'une exception soit survenue ou non (sauf lorsqu'une exception StackOverflowException a été lancée ou qu'un appel a été effectué à Environment.FailFast() ).

Il peut être utilisé pour libérer ou nettoyer les ressources acquises dans le bloc try { ... } toute sécurité.

Console.Write("Please enter a filename: ");
string filename = Console.ReadLine();

Stream fileStream = null;

try
{
    fileStream = File.Open(filename);
}
catch (FileNotFoundException)
{
    Console.WriteLine("File '{0}' could not be found.", filename);
}
finally
{
    if (fileStream != null)
    {
        fileStream.Dispose();
    }
}

Attraper et retracer les exceptions prises

Lorsque vous souhaitez intercepter une exception et faire quelque chose, mais que vous ne pouvez pas continuer à exécuter le bloc de code actuel en raison de l'exception, vous pouvez renvoyer l'exception au gestionnaire d'exceptions suivant dans la pile d'appels. Il y a de bons et de mauvais moyens pour y parvenir.

private static void AskTheUltimateQuestion()
{
    try
    {
        var x = 42;
        var y = x / (x - x); // will throw a DivideByZeroException

        // IMPORTANT NOTE: the error in following string format IS intentional
        // and exists to throw an exception to the FormatException catch, below
        Console.WriteLine("The secret to life, the universe, and everything is {1}", y); 
    }
    catch (DivideByZeroException)
    {
        // we do not need a reference to the exception
        Console.WriteLine("Dividing by zero would destroy the universe.");

        // do this to preserve the stack trace:
        throw;
    }
    catch (FormatException ex)
    {
        // only do this if you need to change the type of the Exception to be thrown 
        // and wrap the inner Exception

        // remember that the stack trace of the outer Exception will point to the
        // next line

        // you'll need to examine the InnerException property to get the stack trace
        // to the line that actually started the problem

        throw new InvalidOperationException("Watch your format string indexes.", ex);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Something else horrible happened. The exception: " + ex.Message);

        // do not do this, because the stack trace will be changed to point to
        // this location instead of the location where the exception
        // was originally thrown:
        throw ex; 
    }
}

static void Main()
{
    try
    {
        AskTheUltimateQuestion();
    }
    catch
    {
        // choose this kind of catch if you don't need any information about 
        // the exception that was caught

        // this block "eats" all exceptions instead of rethrowing them
    }
}

Vous pouvez filtrer par type d'exception et même par propriétés d'exception (nouveau dans C # 6.0, un peu plus long disponible dans VB.NET (citation requise)):

Documentation / C # / nouvelles fonctionnalités

Filtres d'exception

Comme les exceptions C # 6.0 peuvent être filtrées à l'aide de l'opérateur when .

Ceci est similaire à l' aide d' un simple if mais ne se déroule pas la pile si la condition à l' intérieur du when est pas remplie.

Exemple

try
{ 
  // ...
}
catch (Exception e) when (e.InnerException != null) // Any condition can go in here.
{
  // ...
}

La même information peut être trouvée dans les fonctionnalités de C # 6.0 ici: Filtres d'exception

Renvoyer une exception dans un bloc catch

Dans un bloc catch , le mot-clé throw peut être utilisé seul, sans spécifier de valeur d'exception, pour renvoyer l'exception qui vient d'être interceptée. La retransmission d'une exception permet à l'exception d'origine de poursuivre la chaîne de gestion des exceptions, en préservant sa pile d'appels ou les données associées:

try {...}
catch (Exception ex) {
  // Note: the ex variable is *not* used
  throw;
}

Un anti-pattern commun consiste à throw ex à la place throw ex , ce qui a pour effet de limiter la vue du gestionnaire d'exceptions suivant de la trace de la pile:

try {...}
catch (Exception ex) {
  // Note: the ex variable is thrown
  //  future stack traces of the exception will not see prior calls
  throw ex;  
}

En général, l'utilisation de throw ex n'est pas souhaitable, car les futurs gestionnaires d'exceptions qui inspectent la trace de la pile ne pourront voir les appels que dans les throw ex lancés. En omettant la variable ex et en utilisant le mot-clé throw seul, l'exception d'origine " va " .

Lancer une exception à partir d'une méthode différente tout en préservant ses informations

Parfois, vous souhaitez intercepter une exception et la lancer à partir d'un thread ou d'une méthode différente tout en préservant la pile d'exception d'origine. Cela peut être fait avec ExceptionDispatchInfo :

using System.Runtime.ExceptionServices;

void Main()
{
    ExceptionDispatchInfo capturedException = null;
    try
    {
        throw new Exception();
    }
    catch (Exception ex)
    {
        capturedException = ExceptionDispatchInfo.Capture(ex);
    }
    
    Foo(capturedException);
}

void Foo(ExceptionDispatchInfo exceptionDispatchInfo)
{
    // Do stuff

    if (capturedException != null)
    {
        // Exception stack trace will show it was thrown from Main() and not from Foo()
        exceptionDispatchInfo.Throw();
    }
}


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow