In .NET, c'è qualche vantaggio in un try / catch in cui il catch si ripropone [duplicato]

StackOverflow https://stackoverflow.com/questions/1207172

  •  05-07-2019
  •  | 
  •  

Domanda

  

Possibile duplicato:
   Perché catturare e rilanciare l'eccezione in C #?

A volte mi imbatto in codice C # che assomiglia a questo:

        try
        {
            // Some stuff
        }
        catch (Exception e)
        {
            throw e;
        }

Comprendo che è possibile fare qualcosa come registrare il messaggio di eccezione e quindi riprovarlo. Sto parlando di una cattura che rinnova solo l'eccezione. Non vedo un punto a questo. Ho tre domande:

1) C'è qualche vantaggio in questo

2) Questo rallenta affatto il codice

3) Farebbe differenza se il blocco catch fosse il seguente:

        catch (Exception)
        {
            throw;
        }
È stato utile?

Soluzione

Ciò ripete la esatta stessa eccezione:

    catch (Exception)
    {
        throw;
    }

Considerando che ciò rinnova l'eccezione senza la traccia dello stack originale:

    catch (Exception e)
    {
        throw e;
    }

C'è spesso una buona ragione per lanciare; in quanto è possibile registrare l'eccezione o fare altre cose prima di ridisegnare l'eccezione. Non sono a conoscenza di buoni motivi per throw e; poiché cancellerai le preziose informazioni sulla traccia dello stack.

Altri suggerimenti

Non se non fai nient'altro nella cattura ... Ma questo viene spesso usato per fare altre cose nella cattura, come il logging o altri tipi di procedure di eccezione, prima di riproporla.

Uso questa tecnica in modo da poter mettere un punto di interruzione durante il debug. A volte lo rimuovo dopo aver finito ...

La differenza principale è che la traccia dello stack dell'eccezione verrà modificata per mostrare che ha avuto origine dalla posizione del try-catch nel primo esempio.

Il secondo esempio mantiene la traccia dello stack.

C'è un vantaggio

In generale no. Tutto ciò che farà questo modello è reimpostare la traccia dello stack sul punto del nuovo lancio. Ciò renderà più difficile per gli sviluppatori rintracciare l'origine del problema

Rallenta il codice

A tutti? Possibilmente. Rallentalo di qualche differenza misurabile? No.

Farebbe differenza se il blocco catch fosse il seguente?

Sì, la cattura è sostanzialmente completamente ridondante. Riscriverà l'eccezione che manterrà la traccia dello stack originale e non avrà alcun impatto percettibile sulla tua applicazione.

1 - Non vedo alcun vantaggio. Se non gestisci l'eccezione, lascia il tentativo / cattura. L'altro problema con questo esempio è che non stai lanciando l'eccezione effettiva, ma una nuova.

2 - sì - ma a meno che non si trovi in ??un grande ciclo di codice ripetuto, probabilmente non noterai alcuna differenza.

3 - Sì. Nel primo esempio, stai scherzando con il tuo stack di chiamate. Questo esempio mantiene intatto lo stack ribollendo l'eccezione, invece di lanciarne uno nuovo.

Se davvero non stai facendo nient'altro, c'è solo un vantaggio che abbia mai trovato: puoi mettere un punto di interruzione sulla linea lancio . Lo rende molto specifico (piuttosto che rompere ogni volta che viene generato quel tipo di eccezione).

Lo farei solo durante il debug, quindi ripristinerei il codice.

Ho scritto un breve test per mostrare le differenze. Ecco il codice di prova:

try
{
    var broken = int.Parse("null");
}
catch (Exception ex1)
{
    System.Diagnostics.Trace.WriteLine(ex1.ToString());
}

try
{
    try
    {
        var broken = int.Parse("null");
    }
    catch (Exception)
    {
        throw;
    }
}
catch (Exception ex2)
{
    System.Diagnostics.Trace.WriteLine(ex2.ToString());
}

try
{
    try
    {
        var broken = int.Parse("null");
    }
    catch (Exception ex3)
    {
        throw ex3;
    }
}
catch (Exception ex4)
{
    System.Diagnostics.Trace.WriteLine(ex4.ToString());
}

Eseguendo questo, ottengo il seguente output:

A first chance exception of type 'System.FormatException' occurred in mscorlib.dll
System.FormatException: Input string was not in a correct format.
   at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
   at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
   at System.Int32.Parse(String s)
   at QuickTests.Program.Main(String[] args) in C:\Projects\Test\QuickTests\Program.cs:line 18
A first chance exception of type 'System.FormatException' occurred in mscorlib.dll
A first chance exception of type 'System.FormatException' occurred in QuickTests.exe
System.FormatException: Input string was not in a correct format.
   at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
   at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
   at System.Int32.Parse(String s)
   at QuickTests.Program.Main(String[] args) in C:\Projects\Test\QuickTests\Program.cs:line 33
A first chance exception of type 'System.FormatException' occurred in mscorlib.dll
A first chance exception of type 'System.FormatException' occurred in QuickTests.exe
System.FormatException: Input string was not in a correct format.
   at QuickTests.Program.Main(String[] args) in C:\Projects\Test\QuickTests\Program.cs:line 49

Noterai che le prime due eccezioni funzionano allo stesso modo. Quindi, " lancio; " non cambia nulla per quanto riguarda l'eccezione che si sposta nello stack. Tuttavia "getta ex3;" fa sì che l'eccezione segnalata sia diversa, modificando la traccia dello stack per l'eccezione.

Spesso è utile per la registrazione. Inoltre, se si interrompe l'argomento nel rilancio, non altera la traccia dello stack di e.

A volte vuoi consentire attraverso determinati tipi ad es. ecco un'elaborazione speciale per tutto tranne FooException:

try
{
    // ...
}
catch (FooException)
{
    throw;
}
catch (Exception ex)
{
    // handle differently, like wrap with a FooException
    throw new FooException("I pitty the Foo.", ex);
}

Certo.

Molto spesso si desidera registrare l'eccezione prima di lanciarla e forse registrare alcuni valori delle variabili dal metodo.

Solo prenderlo per lanciarlo, però, non ti guadagna molto.

Proprio così, no. Tuttavia, potresti voler fare questo:

catch (Exception ex)
{
     LogException(ex);
     throw;
}

Dove LogException () è una classe personalizzata che, erm, registra l'eccezione o invia un avviso o qualcosa di simile.

Penso che il punto sia garantire che venga generato un solo TIPO di eccezione. È un pessimo IMHO anti-pattern

per es.

try
{
    throw XYZ();
}
catch(Exception e)
{
    throw e;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top