Почему это «наконец» выполняется? - PullRequest
17 голосов
/ 17 июля 2009

Если вы запускаете код, приведенный ниже, он фактически выполняет команду finally после каждого вызова goto:

    int i = 0;
Found:
    i++;
    try
    {
        throw new Exception();
    }
    catch (Exception)
    {
        goto Found;
    }
    finally
    {
        Console.Write("{0}\t", i);
    }

Почему?

Ответы [ 8 ]

36 голосов
/ 17 июля 2009

Следующий текст взят из спецификации языка C # ( 8.9.3 Оператор goto )


Оператор goto выполняется следующим образом:

  • Если оператор goto выходит из одного или нескольких блоков try со связанными блоками finally, управление первоначально передается в блок finally самого внутреннего оператора try. Когда и если управление достигает конечной точки блока finally, управление передается в блок finally следующего включающего оператора try. Этот процесс повторяется до тех пор, пока не будут выполнены блоки finally всех промежуточных операторов try.
  • Управление передается цели оператора goto.
28 голосов
/ 17 июля 2009

Почему вы ожидаете, что он не будет выполнен?

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

Вместо goto рассмотрите возвращение.

//imagine this try/catch/finally block is inside a function with return type of bool. 
try
{
    throw new Exception();
}
catch (Exception)
{
    return false; //Let's say you put a return here, finally block still executes.
}
finally
{
    Console.WriteLine("I am in finally!");
}
13 голосов
/ 17 июля 2009

Суть полученных ответов - что когда контроль покидает защищенную область любыми средствами, будь то «возврат», «переход», «прерывание», «продолжение» или «бросок», выполняется «наконец» - правильный. Тем не менее, я отмечаю, что почти каждый ответ говорит что-то вроде «блок finally всегда выполняется». Блок finally НЕ всегда выполняется. Существует множество ситуаций, в которых блок finally не выполняется.

Кто хочет попытаться перечислить их все?

3 голосов
/ 17 июля 2009

Кажется разумным. Блок finally всегда запускается после try или catch.

Аналогично

try
{
  // do something
  return;
}
finally
{
  // do something else
}

всегда будет запускать блок finally. РЕДАКТИРОВАТЬ - но см. Комментарии Эрика выше.

2 голосов
/ 17 июля 2009

Это по замыслу. В обработчике исключений вы можете предпринять некоторые специфические для исключения действия. В блоке finally вы должны выполнить очистку ресурса - поэтому блок finally всегда выполняется независимо от кода обработки исключений.

1 голос
/ 17 июля 2009

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

0 голосов
/ 13 мая 2010

Это точка блока finally. Он всегда выполняется (в значительной степени).

0 голосов
/ 17 июля 2009

Поскольку оператор finally должен выполняться после выхода из try (или catch при обнаружении исключения). Это включает в себя, когда вы делаете свой goto call.

...