Em C #, o bloco Finally será executado em uma tentativa, catch, finalmente, se uma exceção não tratada for lançada?

Outra pergunta da entrevista que estava esperando uma resposta verdadeira / falsa e eu não tinha muita certeza.

Duplicado

  • No .net, e se algo falhar no bloco catch, finalmente será sempre chamado?
  • Um bloco finalmente funciona sempre?
  • Condições quando finalmente não é executado em um bloco .net try..finally
  • Codificará em um comando Finally statement se eu retornar um valor em um bloco Try?

finally é executado na maioria das vezes . São quase todos os casos. Por exemplo, se uma exceção assíncrona (como StackOverflowException , OutOfMemoryException , ThreadAbortException ) for lançada no encadeamento, a execução finally não será garantida. É por isso que existem regiões de execução restritas para escrever código altamente confiável.

Para fins de entrevista, espero que a resposta a essa pergunta seja falsa (não garantirei nada! A entrevistadora pode não saber disso sozinha!).

Geralmente o bloco finally é garantido para executar.

No entanto, alguns casos forçam o CLR a desligar em caso de erro. Nesses casos, o bloco finally não é executado.

Um exemplo é na presença de uma exceção StackOverflow.

Por exemplo, no código abaixo, o bloco finally não é executado.

 static void Main(string[] args) { try { Foo(1); } catch { Console.WriteLine("catch"); } finally { Console.WriteLine("finally"); } } public static int Foo(int i) { return Foo(i + 1); } 

O outro caso de que estou ciente é se um finalizador lança uma exceção. Nesse caso, o processo também é encerrado imediatamente e, portanto, a garantia não se aplica.

O código abaixo ilustra o problema

 static void Main(string[] args) { try { DisposableType d = new DisposableType(); d.Dispose(); d = null; GC.Collect(); GC.WaitForPendingFinalizers(); } catch { Console.WriteLine("catch"); } finally { Console.WriteLine("finally"); } } public class DisposableType : IDisposable { public void Dispose() { } ~DisposableType() { throw new NotImplementedException(); } } 

Em ambos os casos, o processo termina antes da catch e finally .

Admito que os exemplos são muito artificiais, mas são feitos apenas para ilustrar o ponto.

Felizmente, nem acontece com muita frequência.

Diretamente do MSDN:

O bloco finally é útil para limpar todos os resources alocados no bloco try. O controle é sempre passado para o bloco finally independentemente de como o bloco try sai.

Enquanto catch é usado para tratar exceções que ocorrem em um bloco de instrução, finalmente é usado para garantir que um bloco de instrução de código seja executado independentemente de como o bloco try anterior é encerrado.

http://msdn.microsoft.com/en-us/library/zwc8s4fz(VS.71,loband).aspx

Sim, finalmente é sempre executado.

Não é totalmente verdade que finalmente será sempre executado. Veja esta resposta de Haacked :

Duas possibilidades:

  • StackOverflowException
  • ExecutingEngineException

O bloco finally não será executado quando houver uma StackOverflowException, já que não há espaço na pilha para executar mais código. Ele também não será chamado quando houver um ExecutingEngineException, o que é muito raro.

No entanto, essas duas exceções são exceções das quais você não pode se recuperar, então, basicamente, o processo será encerrado de qualquer maneira.

Como mencionado pelo Mehrdad, um try / catch / finally confiável terá que usar Regiões de Execução Restrita (CER) . Um exemplo é fornecido pelo MSDN:

 [StructLayout(LayoutKind.Sequential)] struct MyStruct { public IntPtr m_outputHandle; } sealed class MySafeHandle : SafeHandle { // Called by P/Invoke when returning SafeHandles public MySafeHandle() : base(IntPtr.Zero, true) { } public MySafeHandle AllocateHandle() { // Allocate SafeHandle first to avoid failure later. MySafeHandle sh = new MySafeHandle(); RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { MyStruct myStruct = new MyStruct(); NativeAllocateHandle(ref myStruct); sh.SetHandle(myStruct.m_outputHandle); } return sh; } } 

Geralmente, o bloco finally é sempre executado, independentemente de uma exceção ser lançada ou não e se alguma exceção é tratada ou não.

Existem algumas exceções (veja outras respostas para mais detalhes).

‘Finally’ é executado independentemente de uma exceção ser lançada ou não.

É um bom lugar para fechar qualquer conexão aberta. Execução bem ou mal sucedida, você ainda pode gerenciar suas conexões ou abrir arquivos.

Finalmente vai acontecer toda vez que tentar catch block

Finalmente, o bloco é garantido para ser executado em qualquer caso.

Finalmente é sempre executado. Eu não depende de como o bloco try funciona. Se vc tiver que fazer algum trabalho extra para try e cath, é melhor colocar finalmente o bloco. Então você pode garantir que seja sempre executado.