yes it does :-) http://msdn.microsoft.com/en-us/library/zwc8s4fz.aspx
Из MSDN try-finally (Справочник по C #)
Блок finally полезен для очистка любых ресурсов, выделенных в блок try, а также запуск любого код, который должен выполняться, даже если есть это исключение. Контроль всегда передается в блок finally независимо о выходе из блока try .
Блок finally будет запущен прямо между этими строками:
message = "You will not win!";
return;
Да, при нормальных обстоятельствах (как указывали многие другие).
Блок finally полезен для очистка любых ресурсов, выделенных в блок try, а также запуск любого код, который должен выполняться, даже если есть это исключение. Контроль всегда передается в блок finally независимо о том, как выходит из блока try.
В то время как ловушка используется для обработки исключения, которые встречаются в заявлении блок, наконец, используется, чтобы гарантировать блок операторов кода выполняется независимо от того, как предыдущая попытка блок закрыт.
Нет, не будет. Он всегда будет выполняться, если приложение все еще запущено (за исключением исключения FastFail, MSDN link, как отметили другие). Он выполнится, когда выйдет из части блока try/catch.
Он НЕ будет выполняться, если приложение аварийно завершается: убивается командой kill process и т.д. Это очень важно, потому что если вы пишете код, который абсолютно ожидает, что он выполнится, например, при ручном выполнении отката, а в противном случае он автоматически зафиксируется, вы можете столкнуться со сценарием, когда приложение прервется до того, как это произойдет. Честно говоря, это внешний сценарий, но его важно учитывать в таких ситуациях.
Из MSDN C# спецификация оператора try
:
Утверждения блока
finally
всегда выполняются, когда управление покидает операторtry
. Это верно независимо от того, происходит ли передача управления в результате обычного выполнения, в результате выполненияbreak
,continue
,goto
илиreturn
оператора, или в результате распространения исключения из оператораtry
.
Есть случаи, когда блок finally не будет выполнен:
Правильный ответ - да.
Попробуйте отладить свою программу и установить точку останова и посмотреть, как элемент управления все еще попадает в блок finally.
Простой ответ Да. Но есть некоторые "исключения" из правила.
Да, finally
всегда выполняется, а вот вызовет ли код в блоке finally исключение - это уже другая история.
Не совсем верно, что finally
всегда будет выполняться. См. этот ответ от Haacked :
Две возможности:
StackOverflowException
ExecutingEngineException
Блок finally не будет выполнен когда есть StackOverflowException поскольку в стеке нет места для даже выполнить еще какой-то код. Так и будет также не называться, когда есть ExecutingEngineException, то есть очень редко.
Фактически, для любого вида асинхронного исключения (например, StackOverflowException
, OutOfMemoryException
, ThreadAbortException
) выполнение блока finally
не гарантируется.
Однако эти исключения являются исключениями, из которых вы обычно не можете восстановить, и в большинстве случаев ваш процесс все равно завершится.
Фактически, есть также как минимум еще один случай, когда finally
не выполняется, как описано Брайаном Расмуссеном в теперь удаленном вопросе :
Другой случай, о котором я знаю, - это если финализатор выдает исключение. В этом если процесс прекращен сразу же, и, следовательно, гарантия не действует.
Приведенный ниже код иллюстрирует проблему
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();
}
}
Надежная попытка / catch / finally должна будет использовать Ограниченные области выполнения (CER) . Пример предоставлен 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;
}
}
Отличным источником информации является следующая статья:
Нет, это не так.
Однако есть только один способ обойти это - Environment.FailFast ()
. См. http://msdn.microsoft.com/de-de/library/ms131100.aspx . Во всех остальных случаях гарантируется выполнение финализаторов; -)
Метод FailFast записывает сообщение строка в приложение Windows журнал событий, создает дамп вашего приложение, а затем завершает текущий процесс. Строка сообщения также включается в отчеты об ошибках Microsoft.
Используйте метод FailFast вместо Метод выхода для прекращения вашего приложение, если состояние вашего приложение повреждено и не подлежит ремонту, и выполнение вашего приложения блоки try / finally и финализаторы будут испорченные программные ресурсы.