Подтвердить что ты не робот

Выполняется ли блок С# "finally" ВСЕГДА?

Возможный дубликат:
Будет ли код в объявлении Окончательный, если я верну его значение в блоке Try?

Рассмотрим следующий код кода С#. Выполняется ли блок "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. Однако, пожалуйста, не стесняйтесь отвечать!

4b9b3361

Ответ 2

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

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

Ответ 3

Из спецификации msdn С# инструкции try.

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

Ссылка источника:

http://msdn.microsoft.com/en-us/library/aa664733(v=VS.71).aspx

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

  • Environment.FailFast
  • Необычные execeptions
  • Сбой питания

Ответ 4

Не совсем верно, что 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();
   }
}

Надежный 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;
    }
}

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

Лучшие рекомендации по надежности

Ответ 5

Из MSDN try-finally (ссылка С#)

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

Ответ 6

Блок finally будет работать прямо между этими строками:

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

Ответ 7

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

Ответ 8

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

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

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

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

Ответ 9

Правильный ответ: Да.

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

Ответ 10

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

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

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

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

Ответ 11

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