2014-11-17 6 views
5

Considera questo piccolo programma. Ignora, se si vuole, la cattura generica, ho mantenuto essere breve per cercare di illustrare il punto:Perché il catch in un metodo di gestione di un'azione tronca la traccia dello stack?

private static void Main(string[] args) 
{ 
    Try(Fail); 
} 

private static void Fail() 
{ 
    var x = ((string)null).Clone(); 
} 

private static void Try(Action action) 
{ 
    try 
    { 
     action(); 
    } 
    catch (Exception exc) 
    { 
     Debug.WriteLine(exc.StackTrace);     
    } 
} 

Quando run, il seguente (con alcune delle informazioni percorso rimosso) viene prodotto:

at Scratch.Program.Fail() in Program.cs:line 27 
at Scratch.Program.Try(Action action) in Program.cs:line 34 

La mia domanda è: perché la traccia dello stack dell'eccezione smette di srotolare la catena del metodo nel metodo Try()? Mi aspetterei che si svolgesse al di fuori del metodo Main().

Non sono stato in grado di trovare alcuna documentazione su ciò che impedisce l'interruzione delle eccezioni andando oltre lo Try() - quindi mi piacerebbe capirlo.

+5

Si sta rilevando l'eccezione in 'Try()', se la si è rilevata in 'Main()', allora è dove finisce la traccia dello stack. –

+2

Questo in realtà non ha nulla a che fare con 'Action', succede anche se hai solo' Try' call 'Fail' direttamente: http://ideone.com/X9JQFS –

risposta

2

Exception.Stacktrace chiamate GetStackTrace che alla fine chiamerà
new StackTrace(this /* exception object */, true). Se utilizzato con questi parametri, la traccia dello stack verrà valutata per il punto dell'eccezione fino al metodo corrente. È possibile verificare che da soli quando si aggiungono

catch (Exception exc) 
{ 
    Debug.WriteLine(new StackTrace()); 
    Debug.WriteLine(new StackTrace(exc, true));   
} 

La seconda versione è la stacktrace restituito dal exc.StackTrace, la prima è la piena StackTrace dal metodo corrente al punto di ingresso o di partenza thread.

+0

Accetto questo perché risponde al domanda senza lasciarmi con ulteriori domande - molte grazie. –

4

questo:

try 
{ 
    action(); 
} 
catch (Exception exc) 
{ 
    Debug.WriteLine(exc.StackTrace);     
} 

cattura l'eccezione all'interno Try, e non si propaga verso l'alto per svolgere il callstack, inghiotte semplicemente l'eccezione. Pertanto, non vedi Main come parte del tuo stacktrace. Se volete vedere Main, lasciare il catch per il metodo di Main:

public static void Main(string[] args) 
{ 
    try 
    { 
     Try(Fail); 
    } 
    catch (Exception e) 
    { 
    } 
} 

E ora si vede:

a ConsoleApplication2.Program.Fail() in C: \ Users \ Yuval \ documents \ visual studio 14 \ Projects \ ConsoleApplication2 \ ConsoleApplication2 \ Program.cs: riga 25 su ConsoleApplication2.Program.Try (Azione azione) in C: \ Users \ Yuval \ documents \ visual studio 14 \ Projects \ ConsoleApplication2 \ ConsoleApplication2 \ Program. cs: linea 30 a ConsoleApplication2.Program.Main (String [] args) in C: \ Users \ Yuval \ Documenti \ Visual Studio 14 \ Projects \ ConsoleApplication2 \ ConsoleApplication2 \ Program.cs: linea 15