Geralmente sim, o finalmente será executado.
Para os três cenários a seguir, o finalmente será sempre executado:
- Nenhuma exceção ocorre
- Exceções síncronas (exceções que ocorrem no fluxo normal do programa).
Isso inclui exceções compatíveis com CLS derivadas de System.Exception e exceções não compatíveis com CLS, que não derivam de System.Exception. Exceções não compatíveis com CLS são agrupadas automaticamente pelo RuntimeWrappedException. O C # não pode gerar exceções de reclamação que não sejam do CLS, mas idiomas como o C ++ podem. O C # pode estar chamando o código escrito em um idioma que pode lançar exceções não compatíveis com CLS.
- ThreadAbortException assíncrono
A partir do .NET 2.0, um ThreadAbortException não impedirá mais que um finalmente seja executado. ThreadAbortException agora é içado para antes ou depois do finalmente. O finalmente sempre será executado e não será interrompido por uma interrupção de encadeamento, desde que a tentativa tenha sido realmente inserida antes da ocorrência do cancelamento de encadeamento.
O cenário a seguir, o finalmente não será executado:
StackOverflowException assíncrono.
A partir do .NET 2.0, um estouro de pilha fará com que o processo seja encerrado. O finalmente não será executado, a menos que uma restrição adicional seja aplicada para tornar o finalmente um CER (Região de Execução Restrita). As RCEs não devem ser usadas no código geral do usuário. Eles devem ser usados apenas onde for crítico que o código de limpeza sempre seja executado - depois que todo o processo for encerrado pelo excesso de pilha de qualquer maneira e, portanto, todos os objetos gerenciados serão limpos por padrão. Portanto, o único local em que um CER deve ser relevante é para recursos alocados fora do processo, por exemplo, identificadores não gerenciados.
Normalmente, o código não gerenciado é agrupado por alguma classe gerenciada antes de ser consumido pelo código do usuário. A classe de wrapper gerenciado normalmente usa um SafeHandle para quebrar o identificador não gerenciado. O SafeHandle implementa um finalizador crítico e um método Release que é executado em um CER para garantir a execução do código de limpeza. Por esse motivo, você não deve ver as CERs espalhadas pelo código do usuário.
Portanto, o fato de finalmente não executar no StackOverflowException não deve afetar o código do usuário, pois o processo será encerrado de qualquer maneira. Se você tem algum caso extremo em que precisa limpar algum recurso não gerenciado, fora de um SafeHandle ou CriticalFinalizerObject, use um CER da seguinte maneira; mas observe que isso é uma prática ruim - o conceito não gerenciado deve ser abstraído para uma classe gerenciada e SafeHandle (s) apropriado (s) por design.
por exemplo,
// No code can appear after this line, before the try
RuntimeHelpers.PrepareConstrainedRegions();
try
{
// This is *NOT* a CER
}
finally
{
// This is a CER; guaranteed to run, if the try was entered,
// even if a StackOverflowException occurs.
}