559 votes

Y a-t-il une différence entre "throw" et "throw ex"?

Il y a déjà des publications qui demandent quelle est la différence entre les deux.
(pourquoi dois-je même mentionner ça...)

Mais ma question est différente dans le sens où j'appelle "throw ex" dans une autre méthode de gestion d'erreur digne d'un dieu.

public class Program {
    public static void Main(string[] args) {
        try {
            // quelque chose
        } catch (Exception ex) {
            HandleException(ex);
        }
    }

    private static void HandleException(Exception ex) {
        if (ex is ThreadAbortException) {
            // ignorer alors,
            return;
        }
        if (ex is ArgumentOutOfRangeException) { 
            // Enregistrer alors,
            throw ex;
        }
        if (ex is InvalidOperationException) {
            // Afficher un message alors,
            throw ex;
        }
        // et ainsi de suite.
    }
}

Si try & catch étaient utilisés dans le Main, alors j'utiliserais throw; pour relancer l'erreur. Mais dans le code simplifié ci-dessus, toutes les exceptions passent par HandleException

Est-ce que throw ex; a le même effet que d'appeler throw lorsqu'il est appelé à l'intérieur de HandleException?

5 votes

Il y a une différence, elle concerne la manière dont la trace de la pile apparaît dans l'exception, mais je ne me souviens pas laquelle est laquelle pour l'instant, donc je ne vais pas la lister comme réponse.

0 votes

@Joel: Merci. Je suppose que l'utilisation de l'exception HandleError est une mauvaise idée. Je voulais juste refactoriser du code de gestion des erreurs.

1 votes

La troisième façon est d'emballer dans une nouvelle exception et de la relancer timwise.blogspot.co.uk/2014/05/…

9voto

Mahesh Points 81

Essayons de comprendre la différence entre throw et throw ex. J'ai entendu dire que cette question commune est posée lors de nombreux entretiens .net.

Pour donner un aperçu de ces deux termes, throw et throw ex sont tous deux utilisés pour comprendre où l'exception s'est produite. Throw ex réécrit la trace de la pile de l'exception, quel que soit l'endroit où elle a réellement été lancée.

Essayons de comprendre avec un exemple.

Commençons par comprendre Throw.

static void Main(string[] args) {
    try {
        M1();
    } catch (Exception ex) {
        Console.WriteLine(" ----------------- Hierarchie de la trace de la pile -----------------");
        Console.WriteLine(ex.StackTrace.ToString());
        Console.WriteLine(" ---------------- Nom de la méthode / Cible -------------- ");
        Console.WriteLine(ex.TargetSite.ToString());
    }
    Console.ReadKey();
}

static void M1() {
    try {
        M2();
    } catch (Exception ex) {
        throw;
    };
}

static void M2() {
    throw new DivideByZeroException();
}

La sortie ci-dessus est la suivante.

montre l'ensemble de la hiérarchie et le nom de la méthode où l'exception s'est réellement produite.. c'est M2 -> M2. ainsi que les numéros de ligne

description de l'image

Deuxièmement.. essayons de comprendre avec throw ex. Remplacez simplement throw par throw ex dans le bloc catch de la méthode M2. comme ci-dessous.

description de l'image

La sortie du code throw ex est la suivante..

description de l'image

Vous pouvez voir la différence dans la sortie.. throw ex ignore simplement toute la hiérarchie précédente et réinitialise la trace de la pile avec la ligne/méthode où throw ex est écrit.

7voto

A.S. Points 123

Microsoft Docs signifie:

Une fois qu'une exception est lancée, une partie des informations qu'elle transporte est la trace de la pile. La trace de la pile est une liste de la hiérarchie des appels de méthode qui commence par la méthode qui lance l'exception et se termine par la méthode qui attrape l'exception. Si une exception est relancée en spécifiant l'exception dans l'instruction throw, la trace de la pile est redémarrée à la méthode actuelle et la liste des appels de méthode entre la méthode d'origine qui a lancé l'exception et la méthode actuelle est perdue. Pour conserver les informations de la trace de la pile d'origine avec l'exception, utilisez l'instruction throw sans spécifier l'exception.

Source: https://learn.microsoft.com/fr-fr/dotnet/fondamentaux/analyse-de-code/règles-de-qualité/ca2200

6voto

Lucero Points 38928

Non, cela provoquera une exception avec une pile d'appels différente. Utiliser uniquement un throw sans aucun objet d'exception dans le gestionnaire catch laissera la pile d'appels inchangée.

Vous pouvez vouloir retourner un booléen depuis HandleException indiquant si l'exception doit être relancée ou non.

3voto

Aaaaaaaa Points 440

Regardez ici: http://blog-mstechnology.blogspot.de/2010/06/throw-vs-throw-ex.html

Lancer:

try 
{
    // faire une opération qui peut échouer
}
catch (Exception ex)
{
    // faire un nettoyage local
    throw;
}

Cela préserve les informations de la pile avec l'exception

Ceci est appelé "Relancer"

Si vous voulez lancer une nouvelle exception,

throw new ApplicationException("opération a échoué!");

Lancer Ex:

try
{
    // faire une opération qui peut échouer
}
catch (Exception ex)
{
    // faire un nettoyage local
    throw ex;
}

Cela ne transmettra pas les informations de la pile avec l'exception

Ceci est appelé "Casser la pile"

Si vous voulez lancer une nouvelle exception,

throw new ApplicationException("opération a échoué!",ex);

3voto

Maksud Points 89

Il vaut mieux utiliser throw au lieu de throw ex.

throw ex réinitialise la trace de la pile d'origine et ne peut pas trouver la trace de pile précédente.

Si nous utilisons throw, nous obtenons une trace de pile complète.

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