40 votes

Pourquoi ne puis-je pas intercepter une exception générique en C #?

Je faisais des tests unitaires sur le code qui pourrait jeter un certain nombre d'exceptions selon les entrées. J'ai donc essayé quelque chose comme le code ci-dessous: (simplifié pour l'exemple)

    static void Main(string[] args)
    {
        RunTest<ArgumentException>();
    }

    static void RunTest<T>() where T : Exception, new()
    {
        try
        {
            throw new T();
            //throw new ArgumentException(); <-- Doesn't work either

        }
        catch (T tex)
        {
            Console.WriteLine("Caught passed in exception type");
        }
        catch (Exception ex)
        {
            Console.WriteLine("Caught general exception");
        }
        Console.Read();
    }

Mais ce sera toujours imprimer "Pris d'exception générale", le catch(T tex) gestionnaire ne marchera jamais. Il n'a pas d'importance si je jette T() ou explicitement jeter ArgumentException(). Toutes les idées de pourquoi il en est? En fait j'ai été un peu surpris de voir que j'ai même été en mesure d'utiliser T dans la clause catch, mais depuis que c'est possible de ne pas ce travail? Ou au moins de donner un compilateur d'avertissement/d'erreur qui dit que ce gestionnaire ne marchera jamais?

Mon environnement est Visual Studio 2008 et 3.5 est la cible de cadre.

Mise à JOUR: j'ai essayé maintenant directement à partir de l'invite de commande et puis il imprime "Pris adopté dans le type d'exception". Donc il semble que c'est limité à l'exécution de Visual Studio. Peut-être une particularité du processus d'hébergement Visual Studio?

34voto

Will Points 76760

Comportement Bizarre ici...

VS2k8 application console. Suivantes:

try
{
    throw new T();
}
catch (T tex)
{
    Console.WriteLine("Caught passed in exception type");
}
catch (Exception ex)
{
    Console.WriteLine("Caught general exception");
}

résultats dans "Pris d'exception générale".

Mais, retirez le (inutile) des variables à partir de la capture des relevés:

try
{
    throw new T();
}
catch (T)
{
    Console.WriteLine("Caught passed in exception type");
}
catch (Exception)
{
    Console.WriteLine("Caught general exception");
}

résultats dans "Pris adopté dans le type d'exception"!!!


Mise à jour:

Heheh... Ses un bug: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=362422&wa=wsignin1.0

Source? Ici. http://stackoverflow.com/questions/700935/why-does-catchtexception-handling-block-behaviour-differ-under-the-debugger-aft

8voto

Guillaume Points 5649

Cela fonctionne sans débogage

http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/0b0e5bc9-fab2-45b1-863b-40abae370475

Solution de contournement laide (vous pouvez ajouter #if DEBUG):

   try
  {
    throw new T();
  }
  catch (Exception dbgEx)
  {
    T ex = dbgEx as T;
    if (ex != null)
    {
      Console.WriteLine(ex.Message);
    }
  }
 

2voto

Damien_The_Unbeliever Points 102139

Il semblerait que les plus spécifiques au type de l'exception, lorsque le choix entre T et d'Exception, est l'exception, et de sorte que le gestionnaire est appelé.

J'ai juste essayé ceci (vous ne pouvez pas le faire en C# ou en VB, mais j'ai édité IL), et changé la seconde clause catch de catch Objet Ex plutôt que l'Exception Ex, et dans ce cas, le premier gestionnaire n'a été touché.

Modifier

Comme d'autres l'ont souligné, c'est plus à voir avec la gestion dans le débogueur que le type spécifique

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