Opa, Rodrigo. Tudo bom?
Quando lançamos uma exceção com a instrução throw <referência de exceção>; estamos avisando onde que esta exceção nasceu e é a partir do método em que esta instrução foi usada que a CLR preencherá o StackTrace.
Quando usamos apenas throw; estamos relançando a exceção criada dentro do bloco try - ou seja, a CLR vai manter o método de origem da exceção.
Exemplo:
1.) throw;
static void ChamaLancaExcecao()
{
try
{
LancaExcecao();
}
catch (Exception e)
{
throw;
}
}
Aqui a CLR mantém a exceção criada no bloco try. O método LancaExcecao continuará na StackTrace.
2.) throw <expressao de excecao>;
static void ChamaLancaExcecao()
{
try
{
LancaExcecao();
}
catch (Exception e)
{
throw e;
}
}
Aqui estamos dizendo onde a exceção nasceu e qual o ponto de partida da StackTrace. O método LancaExcecao não estará na pilha de chamadas!
Por coincidência, estamos lançando uma exceção que capturamos no bloco catch, mas, isto não importa. O que importa para a CLR é darmos uma referência de objeto de exceção e então a máquina virtual vai assumir que foi o método ChamaLancaExcecao que originou a exceção.
O que você acha? Ajudei com sua dúvida?
Abs.