Tenho o seguinte código
using(MemoryStream ms = new MemoryStream())
{
//code
return 0;
}
O dispose()
método é chamado no final das using
chaves de instrução, }
certo? Já que eu return
antes do final do using
enunciado, o MemoryStream
objeto será descartado corretamente? o que acontece aqui?
Respostas:
Sim,
Dispose
será chamado. É chamado assim que a execução sai do escopo dousing
bloco, independentemente do meio que levou para sair do bloco, seja o fim da execução do bloco, umareturn
instrução ou uma exceção.Como @Noldorin corretamente aponta, o uso de um
using
bloco no código é compilado emtry
/finally
,Dispose
sendo chamado nofinally
bloco. Por exemplo, o seguinte código:efetivamente se torna:
Portanto, como
finally
tem garantia de execução após otry
bloco ter concluído a execução, independentemente de seu caminho de execução,Dispose
é garantido que será chamado, não importa o quê.Para obter mais informações, consulte este artigo do MSDN .
Adendo:
apenas uma pequena advertência a ser adicionada: como
Dispose
é garantido que será chamado, é quase sempre uma boa ideia garantir queDispose
nunca lance uma exceção ao implementarIDisposable
. Infelizmente, existem algumas classes na biblioteca central que fazer lance em determinadas circunstâncias, quandoDispose
é chamado - Eu estou olhando para você, Proxy WCF Serviço de Referência / Cliente! - e quando isso acontece, pode ser muito difícil rastrear a exceção original se elaDispose
foi chamada durante o desenrolamento de uma pilha de exceções, uma vez que a exceção original é engolida em favor da nova exceção gerada pelaDispose
chamada. Pode ser enlouquecedoramente frustrante. Ou isso é frustrantemente enlouquecedor? Um dos dois. Talvez ambos.fonte
Dispose
in finally, portanto, está efetivamente trabalhando na implementação definally
, conforme você descreve.using
as instruções se comportam exatamente comotry ... finally
blocos, portanto, sempre serão executadas em quaisquer caminhos de saída de código. No entanto, acredito que eles estão sujeitos às raras e raras situações em que osfinally
blocos não são chamados. Um exemplo que posso lembrar é se o encadeamento em primeiro plano sai enquanto os encadeamentos em segundo plano estão ativos: todos os encadeamentos exceto o GC são pausados, o que significa que osfinally
blocos não são executados.Edição óbvia: eles se comportam da mesma forma, independentemente da lógica que os permite manipular objetos ID descartáveis, d'oh.
Conteúdo bônus: eles podem ser empilhados (onde os tipos são diferentes):
E também delimitado por vírgulas (onde os tipos são iguais):
fonte
Seu objeto MemoryStream será descartado corretamente, não há necessidade de se preocupar com isso.
fonte
Com a
using
instrução, o objeto será descartado independentemente do caminho de conclusão.Leitura adicional ...
fonte
Dê uma olhada em seu código no reflector depois de compilá-lo. Você descobrirá que o compilador refatora o código para garantir que dispose seja chamado no fluxo.
fonte