Не совсем верно, что finally
всегда будет выполняться.См this answer от Haacked:
две возможности:
StackOverflowException
ExecutingEngineException
Окончательно блок не будут выполнены , когда есть StackOverflowException так как нет места на стек до даже exec ute больше кода. Он будет также не будет называться, когда есть ExecutingEngineException, которое очень редко.
В самом деле, для любого вида асинхронного исключения (как StackOverflowException
, OutOfMemoryException
, ThreadAbortException
) выполнение в finally
блока не гарантируется.
Однако эти исключения являются исключениями, от которых обычно не удается восстановить, и в большинстве случаев ваш процесс все равно выйдет.
В самом деле, есть и по крайней мере один другой случай, когда finally
не выполняется, как описано Brian Rasmussen в настоящее deleted question:
Другой случай я в курсе, если финализации бросает исключение , В этом случае немедленно прекращается процесс , и, следовательно, гарантия не применяется.
Приведенный ниже код иллюстрирует проблему
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();
}
}
Надежный TRY/поймать/наконец, придется использовать Constrained Execution Regions (CER). example обеспечивается 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;
}
}
отличным источником информации является следующая статья:
Reliability Best Practices
Нет. Вы получите ошибку компилятора. – Zano
Единственное, что не компилируется, - это пропущенная точка с запятой после объявления «ext». –
@ Zano - Отсутствует; была опечатка :) –