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/…

2voto

Aussi, en .NET 1.1 throw lancera également des exceptions non .NET

1voto

Timbo Points 472

Pour compléter la réponse de Lucero, voici comment vous pouvez accomplir l'intention du code original sans perdre la trace de la pile d'origine.

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

    /// 
    ///   true si l'exception a été gérée;
    ///   false si l'exception doit être transmise
    /// 
    private static bool HandleException(Exception ex) {
        if (ex is ThreadAbortException) {
            // ignorer alors,
            return true;
        }
        if (ex is ArgumentOutOfRangeException) { 
            // Enregistrer alors,
            return false;
        }
        if (ex is InvalidOperationException) {
            // Afficher un message alors,
            return false;
        }
        // et ainsi de suite.
    }
}

0voto

Charles Owen Points 533

Pour vous donner une perspective différente sur cela, l'utilisation de throw est particulièrement utile si vous fournissez une API à un client et que vous voulez fournir des informations de trace de pile détaillées pour votre bibliothèque interne. En utilisant throw ici, j'obtiendrais la trace de pile dans ce cas de la bibliothèque System.IO.File pour File.Delete. Si j'utilise throw ex, alors cette information ne sera pas transmise à mon gestionnaire.

static void Main(string[] args) {
   Method1();
}

static void Method1() {
   try {
       Method2();
   } catch (Exception ex) {
       Console.WriteLine("Exception dans la Méthode 1");
   }
}

static void Method2() {
   try {
       Method3();
   } catch (Exception ex) {
       Console.WriteLine("Exception dans la Méthode 2");
       Console.WriteLine(ex.TargetSite);
       Console.WriteLine(ex.StackTrace);
       Console.WriteLine(ex.GetType().ToString());
   }
}

static void Method3() {
   Method4();
}

static void Method4() {
   try {
       System.IO.File.Delete("");
   } catch (Exception ex) {
       // Afficher toute la trace de pile dans le .NET
       // ou bibliothèque personnalisée jusqu'à Method2() où l'exception est gérée
       // Si vous souhaitez obtenir la trace de pile la plus détaillée
       // dans les entrailles de la bibliothèque que vous appelez
       throw;
       // throw ex;
       // Afficher la trace de pile de Method4() à Method2() où l'exception est gérée
   }
}

-2voto

Bhanu pratap Points 65
int a = 0;
try {
    int x = 4;
    int y ;
    try {
        y = x / a;
    } catch (Exception e) {
        Console.WriteLine("inner ex");
        //throw;   // Ligne 1
        //throw e;   // Ligne 2
        //throw new Exception("devide by 0");  // Ligne 3
    }
} catch (Exception ex) {
    Console.WriteLine(ex);
    throw ex;
}
  1. if all Ligne 1 ,2 and 3 are commented - Output - inner ex

  2. if all Ligne 2 and 3 are commented - Output - inner ex System.DevideByZeroException: {"Attempted to divide by zero."}---------

  3. if all Ligne 1 and 2 are commented - Output - inner ex System.Exception: devide by 0 ----

  4. if all Ligne 1 and 3 are commented - Output - inner ex System.DevideByZeroException: {"Attempted to divide by zero."}---------

and StackTrace will be reset in case of throw ex;

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