Vi essa dica em outra pergunta e fiquei imaginando se alguém poderia me explicar como isso funciona.
try { return x; } finally { x = null; }
Quero dizer, a finally
cláusula realmente é executada após a return
declaração? Quão inseguro é esse código? Você consegue pensar em alguma try-finally
invasão adicional que possa ser feita através dessa invasão?
c#
.net
exception-handling
Dmitri Nesteruk
fonte
fonte
A instrução finalmente é executada, mas o valor de retorno não é afetado. A ordem de execução é:
Aqui está um pequeno programa para demonstrar:
Isso imprime "try" (porque é isso que é retornado) e depois "finalmente" porque esse é o novo valor de x.
Obviamente, se retornarmos uma referência a um objeto mutável (por exemplo, um StringBuilder), todas as alterações feitas no objeto no bloco finally serão visíveis no retorno - isso não afetou o próprio valor de retorno (que é apenas um referência).
fonte
return
declaração, e esse valor será retornado. A expressão não é avaliada como o controle sai do método.A cláusula finally é executada após a declaração de retorno, mas antes de realmente retornar da função. Isso tem pouco a ver com a segurança dos fios, eu acho. Não é um hack - o finalmente é garantido para sempre executar, não importa o que você faça no bloco try ou no bloco catch.
fonte
Além das respostas dadas por Marc Gravell e Jon Skeet, é importante observar que objetos e outros tipos de referência se comportam de maneira semelhante quando retornados, mas existem algumas diferenças.
O "O quê" retornado segue a mesma lógica dos tipos simples:
A referência que está sendo retornada já foi avaliada antes da variável local receber uma nova referência no bloco final.
A execução é essencialmente:
A diferença é que ainda seria possível modificar tipos mutáveis usando as propriedades / métodos do objeto que podem resultar em comportamentos inesperados, se você não tomar cuidado.
Uma segunda coisa a considerar sobre try-return-finalmente é que os parâmetros passados "por referência" ainda podem ser modificados após o retorno. Somente o valor de retorno foi avaliado e é armazenado em uma variável temporária aguardando retorno, quaisquer outras variáveis ainda são modificadas da maneira normal. O contrato de um parâmetro de saída pode até não ser cumprido até o bloqueio final dessa maneira.
Como qualquer outra construção de fluxo, "try-return-finalmente" tem seu lugar e pode permitir um código com aparência mais limpa do que escrever a estrutura na qual ele realmente compila. Mas deve ser usado com cuidado para evitar pegadinhas.
fonte
Se
x
for uma variável local, não vejo o ponto, poisx
será efetivamente definido como nulo de qualquer maneira quando o método for encerrado e o valor do valor de retorno não for nulo (desde que foi colocado no registro antes da chamada para definirx
para nulo).Só posso ver isso acontecendo se você quiser garantir a alteração do valor de um campo no retorno (e após a determinação do valor de retorno).
fonte