remarks - docblock c#




Qual é a maneira correta de lançar novamente uma exceção em c#? (6)

Depende. Em uma compilação de depuração, quero ver o rastreamento de pilha original com o mínimo de esforço possível. Nesse caso, "jogar"; Se encaixa na conta. Em uma compilação de lançamento, no entanto, (a) desejo registrar o erro com o rastreamento de pilha original incluído e, uma vez feito isso, (b) refazer o tratamento de erros para fazer mais sentido para o usuário. Aqui "Throw Exception" faz sentido. É verdade que o relançamento do erro descarta o rastreio de pilha original, mas um não desenvolvedor obtém nada além de ver as informações de rastreio de pilha, portanto, não há problema em relançar o erro.

        void TrySuspectMethod()
        {
            try
            {
                SuspectMethod();
            }
#if DEBUG
            catch
            {
                //Don't log error, let developer see 
                //original stack trace easily
                throw;
#else
            catch (Exception ex)
            {
                //Log error for developers and then 
                //throw a error with a user-oriented message
                throw new Exception(String.Format
                    ("Dear user, sorry but: {0}", ex.Message));
#endif
            }
        }

A maneira como a pergunta é redigida, colocando "Throw:" vs. "Throw ex"; torna um pouco de arenque vermelho. A escolha real é entre "Jogue"; e "Throw Exception", em que "Throw ex"; é um caso especial improvável de "Exceção de lançamento".

Esta questão já tem uma resposta aqui:

Eu tenho uma pergunta para você que deriva do meu parceiro fazendo as coisas de uma maneira diferente da minha.

É melhor fazer isso:

try
{
    ...
}
catch (Exception ex)
{
    ...
    throw;
}

ou isto:

try
{
    ...
}
catch (Exception ex)
{
    ...
    throw ex;
}

Eles fazem a mesma coisa? Um é melhor que o outro?


Descobri que, se a exceção for lançada no mesmo método em que é capturada, o rastreamento de pilha não será preservado, pelo que vale a pena.

void testExceptionHandling()
{
    try
    {
        throw new ArithmeticException("illegal expression");
    }
    catch (Exception ex)
    {
        throw;
    }
    finally
    {
        System.Diagnostics.Debug.WriteLine("finally called.");
    }
}

Minhas preferências é usar

try 
{
}
catch (Exception ex)
{
     ...
     throw new Exception ("Put more context here", ex)
}

Isso preserva o erro original, mas permite que você coloque mais contexto, como um ID de objeto, uma string de conexão, coisas assim. Muitas vezes, minha ferramenta de relatório de exceções tem 5 exceções encadeadas para relatar, cada uma relatando mais detalhes.


O primeiro é melhor. Se você tentar depurar o segundo e examinar a pilha de chamadas, não verá de onde veio a exceção original. Existem truques para manter a pilha de chamadas intacta (tente pesquisar, ela já foi respondida antes) se você realmente precisa voltar a jogar.


Se você lançar uma exceção sem uma variável (o segundo exemplo), o StackTrace incluirá o método original que lançou a exceção.

No primeiro exemplo, o StackTrace será alterado para refletir o método atual.

Exemplo:

static string ReadAFile(string fileName) {
    string result = string.Empty;
    try {
        result = File.ReadAllLines(fileName);
    } catch(Exception ex) {
        throw ex; // This will show ReadAFile in the StackTrace
        throw;    // This will show ReadAllLines in the StackTrace
    }

Você deve sempre usar "jogar"; para relançar as exceções no .net,

Consulte isto, http://weblogs.asp.net/bhouse/archive/2004/11/30/272297.aspx

Basicamente MSIL (CIL) tem duas instruções - "throw" e "rethrow" e "throw ex" do C #; é compilado em "throw" do MSIL e "throw" do C #; - em MSIL "rethrow"! Basicamente, eu posso ver a razão pela qual "throw ex" substitui o rastreamento de pilha.





exception-handling