Em .NET, há alguma vantagem para um try / catch onde a captura apenas relança [duplicado]

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

  •  05-07-2019
  •  | 
  •  

Pergunta

Duplicate possíveis:
Por captura e Exceção rethrow em C #?

Às vezes, se deparar com C # código que se parece com isso:

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

Eu entendo a sua possível fazer algo como registrar a mensagem de exceção e, em seguida, relançar-lo. Estou falando de um prendedor que só relança a exceção. Eu não vejo um ponto para isso. Eu tenho três perguntas:

1) Existe alguma vantagem para este

2) Será que esta doen lento o código em tudo

3) Faria alguma diferença se o bloco catch foram os seguintes:

        catch (Exception)
        {
            throw;
        }
Foi útil?

Solução

Esta relança o exata mesma exceção:

    catch (Exception)
    {
        throw;
    }

Considerando que a presente relança a exceção sem o rastreamento de pilha original:

    catch (Exception e)
    {
        throw e;
    }

Muitas vezes há uma boa razão para throw; como você pode registrar a exceção ou fazer outras coisas antes de rethrowing a exceção. Não tenho conhecimento de quaisquer boas razões para throw e; como você vai acabar com as valiosas informações rastreamento de pilha.

Outras dicas

Não se você não fizer nada mais na captura ... Mas isso é muitas vezes usado para fazer outras coisas na captura, como a extração de madeira, ou outros tipos de procesing exceção, antes rethrowing-lo.

Eu uso essa técnica para que eu possa colocar um ponto de interrupção no lance quando a depuração. Às vezes eu removê-lo depois que eu sou feito ...

A principal diferença é que o rastreio da pilha de excepção será alterado para mostrar que se originou a partir do local da tentativa-captura no primeiro exemplo.

O segundo exemplo mantém o rastreamento de pilha.

Existe uma vantagem

Normalmente, não há falar. Todos este padrão vai fazer é redefinir o rastreamento de pilha, a ponto do novo lançamento. Isso só vai tornar mais difícil para os desenvolvedores a rastrear a origem do problema

Será que retardar o código em tudo

Em todos? Possivelmente. Retardá-lo por qualquer diferença mensurável? Não.

Faria alguma diferença se o bloco catch foram os seguintes?

Sim, essa captura é essencial e completamente redundante. Ele vai relançar a exceção que irá manter o rastreamento de pilha original e não têm impacto percievable em sua aplicação.

1 - Não vejo qualquer vantagem em tudo. Se você não está lidando com a exceção, deixar o try / catch off. O outro problema com este exemplo é que você não está jogando a exceção real, mas um novo.

2 - Sim. - mas a menos que isso está sentado em um grande laço de código repetido, você provavelmente não vai notar uma diferença

3 - Sim. No primeiro exemplo, você está brincando com a sua pilha de chamadas. Este exemplo mantém a pilha intacta por borbulhando a exceção, em vez de jogar um novo.

Se você está realmente fazendo nada mais, só há uma vantagem que eu já encontrados: você pode colocar um ponto de interrupção na linha throw. Isso torna muito específico (ao invés de apenas quebrar sempre que esse tipo de exceção é lançada).

Eu só faria isso durante a depuração no entanto, em seguida, reverter a parte de trás de código.

Eu escrevi um teste rápido para mostrar as diferenças. Aqui está o código de teste:

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

A execução deste, eu recebo o seguinte resultado:

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

Você notará que as duas primeiras exceções são funcionam da mesma maneira. Assim, "jogar"; não muda nada, tanto quanto a ressalva de que se move para cima da pilha. No entanto "jogar ex3"; faz com que a exceção relatado para ser diferente, mudando o rastreamento de pilha da exceção.

Muitas vezes é bom para o registo. Além disso, se você deixar de fora o argumento na re-lançar, em seguida, ele não altera o rastreamento de pilha de e.

Às vezes você deseja permitir através de certos tipos exemplo aqui está um processamento especial para tudo, mas FooException:

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

Claro.

Na maioria das vezes você quiser registrar a exceção antes de jogá-lo, e talvez gravar alguns valores variáveis ??do método.

Apenas captura-lo para jogá-lo, porém, não ganhar-lhe um monte.

Assim como essa, não. No entanto, você pode querer fazer isso:

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

Onde LogException () é uma classe personalizada que, erm, registra a exceção ou e-mails um alerta ou algo assim.

Eu acho que o ponto é para garantir que apenas um tipo de exceção é lançada. É um muito ruim IMHO anti-padrão

por exemplo.

try
{
    throw XYZ();
}
catch(Exception e)
{
    throw e;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top