No es totalmente cierto que finally
siempre se ejecutará.Ver this answer de Haacked:
dos posibilidades:
StackOverflowException
ExecutingEngineException
El bloque finally no se ejecutará cuando hay una StackOverflowException ya que no hay espacio en la apilar hasta incluso ejecutivo Ute más código Tampoco se llamará a cuando existe una excepción ExecutingEngineException, que es muy rara.
De hecho, para cualquier tipo de excepción asíncrona (como StackOverflowException
, OutOfMemoryException
, ThreadAbortException
) la ejecución de un bloque finally
no está garantizada.
Sin embargo, estas excepciones son excepciones de las que generalmente no puede recuperarse, y en la mayoría de los casos su proceso se cerrará de todos modos.
De hecho, también hay al menos otro caso en el que finally
no se ejecuta como se describe por Brian Rasmussen en un momento deleted question:
El otro caso soy consciente de que es si un finalizador se emite una excepción . En ese caso , el proceso finaliza también en , por lo que la garantía no se aplica.
El código siguiente ilustra el 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();
}
}
Un try fiable/catch/finally tendrá que utilizar Constrained Execution Regions (CER). Un example se proporciona por 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;
}
}
una excelente fuente de información es el siguiente artículo:
Reliability Best Practices
No. Obtendrás un error de compilación. – Zano
Lo único que no se compila es el punto y coma faltante después de declarar 'ext'. –
@Zano - La faltante; fue un error tipográfico :) –