Всегда ли выполняется блок C# "finally"? [дубликат]


Возможные Дубликаты:
будет ли код в конечном счете срабатывать, если я возвращаю значение в блоке Try?

рассмотрим следующий код на C#. Выполняется ли блок" finally"?

public void DoesThisExecute() {
   string ext = "xlsx";
   string message = string.Empty;
   try {
      switch (ext) {
         case "xls": message = "Great choice!"; break;
         case "csv": message = "Better choice!"; break;
         case "exe": message = "Do not try to break me!"; break;
         default:
            message = "You will not win!";
            return;
      }
   }
   catch (Exception) {
      // Handle an exception.
   }
   finally {
      MessageBox.Show(message);
   }
}

ха, после того, как я закончил писать это, я понял, что мог бы сделать это сам в Visual Studio. Однако, пожалуйста, не стесняйтесь отвечать!

11 59

11 ответов:

нет это не так. Он всегда будет выполняться при условии, что приложение все еще работает (за исключениемFastFail исключения MSDN link, как и другие отметили). Он будет выполняться при выходе из части try / catch блока.

Он не будет выполняться, если приложение аварийно завершает работу: убивается через команду процесса убийства и т. д. Это очень важно, потому что если вы пишете код, который абсолютно ожидает его запуска, например, вручную выполнить откат, и если это не будет автоматически зафиксировано, вы можете запустить сценарий, который приложение прерывает, прежде чем это произойдет. Честно говоря, это внешний сценарий, но важно принять к сведению в этих ситуациях.

из спецификации MSDN C#try о себе:

заявления finally блок всегда выполняется, когда элемент управления покидает a try заявление. Это верно, если передача управления происходит в результате нормального выполнения, в результате выполнения break,continue,goto или return оператор, или в результате распространения исключения из try заявление.

источник

бывают случаи, когда блок finally не будет выполняться:

  1. окружающая среда.Содержащие
  2. Неуловимые типы исключений
  3. Сбой Питания

это не совсем верно, что finally всегда будет выполняться. Смотрите ответ С Haacked:

два варианта:

  • StackOverflowException
  • ExecutingEngineException

блок finally не будет выполнен когда есть исключение StackOverflowException так как нет места в стеке даже выполнить любой другой код. Оно будет также не будет называться, когда есть ExecutingEngineException, который является очень редко.

фактически, для любого вида асинхронного исключения (например StackOverflowException,OutOfMemoryException,ThreadAbortException) исполнение a finally блока не гарантируется.

однако эти исключения являются исключениями, которые вы обычно не можете восстановить, и в большинстве случаев ваш процесс все равно завершится.

в самом деле, есть также по крайней мере один случай, когда finally не выполняется, как описано Брайан Расмуссен в настоящее время удаленный вопрос:

другой случай, о котором я знаю, если a финализатор создает исключение. В том случае процесс прекращается сразу же, а значит и гарантия не распространяется.

приведенный ниже код иллюстрирует проблему

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 / catch / наконец-то придется использовать ограниченные области выполнения (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;
    }
}

отличным источником информации является следующая статья:

Рекомендации По Надежности

от MSDN try-finally (ссылка на C#)

блок finally полезен для очистка любых ресурсов, выделенных в блок try, а также запуск любого код, который должен выполняться, даже если есть являться исключением. управление всегда передано в блок finally независимо о том, как блок try выходит.

наконец блок будет работать, прямо между этими строками:

message = "You will not win!";
return;

да finally всегда выполняется, теперь независимо от того, вызовет ли код в блоке finally исключение, это другая история.

правильный ответ-да.

попробуйте отладить свою программу и поставить точку останова и смотреть, как контроль все еще попадает в блок finally.

нет это не так.

есть только один способ обойти это, хотя и это Environment.FailFast(). См.http://msdn.microsoft.com/de-de/library/ms131100.aspx. в любом другом случае гарантируется выполнение финализаторов ;-)

метод FailFast записывает сообщение строка для приложения Windows журнал событий, создает дамп применение, и после этого прекращает текущий процесс. Строка сообщения является также включены в ошибку отчетность Microsoft.

используйте метод FailFast вместо Метод выхода для завершения работы применение если государство вашего приложение повреждено и не подлежит ремонту, и выполнение вашего приложения попробуйте / наконец блоки и финализаторы будут коррумпированные ресурсы программы.

да, при нормальных обстоятельствах (как указывали многие другие).

блок finally полезен для очистка любых ресурсов, выделенных в блок try, а также запуск любого код, который должен выполняться, даже если есть являться исключением. Контроль есть всегда передано в блок finally независимо о том, как блок try выходит.

в то время как catch используется для обработки исключения, возникающие в инструкции блок, наконец, используется, чтобы гарантировать блок инструкций кода выполняется независимо от того, как предыдущая попытка блок выходит.

http://msdn.microsoft.com/en-us/library/zwc8s4fz.aspx

простой ответ "да". Но есть некоторые "исключения" из правил.