Para um típico if...else
empacotado com manipulação de exceção, é algo como o exemplo a seguir uma prática recomendada para evitar a duplicação de código?
try
{
if (GetDataFromServer())
{
return ProcessData();
}
else
{
throw new Exception();
}
catch(Exception ex)
{
return null;
}
ao invés de...
try
{
if (GetDataFromServer())
{
return ProcessData();
}
else
{
return null;
}
}
catch(Exception ex)
{
return null;
}
Sei que há um pequeno impacto no desempenho, mas estou me perguntando se isso é considerado uma prática aceitável. Atualmente, faço o segundo método - especialmente nos casos em que preciso lidar com exceções específicas de maneira diferente - mas fiquei pensando se o primeiro método é apropriado para casos simples.
c#
exception-handling
grovesNL
fonte
fonte
Respostas:
O uso de manipulação de exceção para controle de fluxo é desencorajado pela Microsoft.
E uma mesa redonda sobre o tema está disponível.
Dito isto, o C # suporta isso, e suponho que depende da condição encontrada se uma exceção é a resposta mais apropriada.
fonte
O impacto no desempenho é provavelmente insignificante, conforme explicado nesta resposta .
Então, vamos com a ideia de que o desempenho não é um problema. Você está jogando
System.Exception
, apenas para mover a execução para acatch
cláusula . Jogar umBadControlFlowThatShouldBeRewrittenException
provavelmente seria um exagero.Vamos quebrar isso. Nós temos:
GetDataFromServer
(os nomes dos métodos devem ser PascalCase em C #), o que pode gerar uma exceção ou retornar abool
.true
, executeProcessData
.null
caso contrário.Parece que o método em que esse código está escrito está simplesmente fazendo muitas coisas.
GetDataFromServer
retornando umabool
aparência de falha de design, eu esperaria que esse método retornasse os dados obtidos do servidor , algunsIEnumerable<SomeType>
que contenham 0 ou mais itens - ou seja, o caminho feliz retorna n itens em que n> 0 , não tão feliz path retorna 0 itens e o caminho infeliz explode com uma exceção não tratada, seja o que for.Isso muda bastante a aparência do método - novamente, é difícil dizer se isso faz sentido, porque a postagem original tem apenas um ponto de saída (e, portanto, não seria compilado, pois nem todos os caminhos de código retornam um valor ), então este é apenas um palpite:
Aqui você observaria
ProcessData
e iteraria oeresult
retornaránull
se não houver nenhum item noIEnumerable
.Agora, por que o método está retornando
null
? O servidor estava inoperante? Existe um erro na consulta? A cadeia de conexão está usando as credenciais incorretas? Sempre queGetDataFromServer
explode com uma exceção que você não está esperando, você está engolindo, empurrando-a para debaixo do tapete e retornando umnull
valor. Eu recomendo capturar exceções específicas nesse caso e registrar todo o resto; a depuração será muito mais fácil dessa maneira.Com uma
catch
cláusula geral que não captura a exceção, fica muito difícil diagnosticar qualquer coisa. Eu faria isso minimamente:Agora você pode pelo menos quebrar e inspecionar
e
se as coisas derem errado.TL; DR : Não, lançar e capturar exceções para controle de fluxo não é uma boa ideia.
fonte
na sua primeira resposta, há um impacto no desempenho que não precisa estar lá.
quando você sai da instrução if para entrar na instrução Catch quando não precisa fazer o código mudar de direção, por assim dizer.
se você quiser
return null;
fazê-lo na instrução else, não em uma captura que é capturada após ser lançada da instrução else.Provavelmente não se aplica ao seu código Real , mas se aplica ao código genérico que você forneceu.
Os padrões dizem que você não deve fazer isso.
Os padrões dizem que você deve fazer assim (novamente baseado no código genérico fornecido no OP)
e como você não tem nenhuma exceção específica que está capturando, não deve tentar aqui.
você deseja ver exceções quando elas ocorrerem, para que você possa corrigir o problema que cria a exceção.
fonte
Por que não o muito mais simples:
Se um manipulador de exceção existir, ele deve estar em ProcessData ()
fonte
ProcessData()
para o nível superior?ProcessData()
lança uma exceção agora, não é tratada. Eu quero quereturn null
neste nível seProcessData()
lança uma exceção, sem se modificarProcessData()
.