2009-10-16 2 views
39

Stavo eseguendo alcuni test di unità sul codice che potevano generare una serie di eccezioni a seconda degli input. Così ho provato qualcosa di simile il codice qui sotto: (semplificato per l'esempio)Perché non riesco a rilevare un'eccezione generica in C#?

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(); 
    } 

ma questo sarà sempre stampare "Preso un'eccezione generale", il catch (T tex) gestore non funzionerà mai. Non importa se lancio T() o lancio esplicitamente ArgumentException(). Qualche idea del perché questo? In realtà sono stato un po 'sorpreso dal fatto che ero persino in grado di usare T nella clausola catch, ma dato che è possibile non dovrebbe funzionare? O almeno dare un avvertimento/errore del compilatore che dice che questo gestore non funzionerà mai?

Il mio ambiente è Visual Studio 2008 e 3.5 è il framework di destinazione.

UPDATE: l'ho provato ora direttamente dal prompt dei comandi e poi viene stampato "Caught passed in exception type". Quindi sembra che questo sia limitato all'esecuzione da Visual Studio. Forse una peculiarità del processo di hosting di Visual Studio?

+1

ho appena provato in LINQPad e stampato Caught passato nel tipo di eccezione. Puoi fornire maggiori dettagli sul tuo ambiente e sulla versione del framework. –

+2

È interessante. L'ho eseguito come app per console in VS2008 e ha stampato un'eccezione generale Caught. –

+0

Funziona anche in app SnippetCompiler –

risposta

32

Comportamento bizzarro qui ...

App console VS2k8. Il seguente:

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

risultati in "eccezione generale Preso".

Ma, rimuovere le variabili (inutile) dalle dichiarazioni di cattura:

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

risultati in "Preso approvata nel tipo di eccezione" !!!


Aggiornamento:

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

Source? Qui. Why does catch(TException) handling block behaviour differ under the debugger after installing Visual Studio 2008?

2

Sembrerebbe che il tipo più specifico di eccezione, quando somministrato la scelta tra T e Exception è un'eccezione e quindi viene richiamato il gestore.

Ho appena provato questo (non è possibile farlo in C# o VB, ma ho modificato l'IL) e modificato la seconda clausola di cattura per catturare Object Ex piuttosto che Exception Ex, e in tal caso, il primo gestore è stato colpito

Modifica

Come altri hanno fatto notare, è più a che fare con l'esecuzione nel debugger che il tipo specifico