2009-07-17 3 views
17

Если вы запустите приведенный ниже код он на самом деле выполняет наконец после каждого вызова Goto:Почему это «наконец» выполняется?

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

Почему?

+12

-1 для использования GOTO –

+8

Я не делал этого в производственном коде. Это была всего лишь гипотетическая ситуация. – Kredns

+1

Основная причина для голосования: я думал, что это вопрос нуба, после получения более 4 тыс. Баллов !!! Извините ... :) –

ответ

28

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

Если у вас есть попытка/уловка/наконец или попытка/окончательный блок, то, наконец, блок выполняет независимо от того, какой код вы можете иметь в блоке try или catch most of the time.

Вместо того, чтобы перейти, рассмотрим «возвращение».

//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!"); 
} 
+0

Я думаю, я думал, что goto переопределит это. – Kredns

+0

Никакая конструкция не может отменить это поведение. 'goto'/'return'/любая другая конструкция, которую вы можете себе представить. – SolutionYogi

+2

Что произойдет, если у вас есть «return true»; в блоке finally (против приведенного выше примера кода). что получилось? ложное или истинное? –

2

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

3

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

Аналогично

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

будет всегда запускать finally блок. EDIT - но см. Комментарии Эрика выше.

0

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

37

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


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

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

+1 для ссылки на спецификацию. –

+0

+1 для ссылки на спецификацию тоже. –

+0

Бог! Спецификация довольно длинная ;-) – Kredns

1

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

12

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

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

+0

Согласно спецификации «Операторы блока finally всегда выполняются, когда элемент управления оставляет оператор try.Это верно, происходит ли передача управления в результате нормального выполнения в результате выполнения оператор break, continue, goto или return или в результате распространения исключения из инструкции try. " Однако я бы сказал, что исключение StackOverflowException - одно, потому что ничто не может справиться с этим, насколько я могу судить. –

+1

Колин, действительно, ключевым моментом является КОГДА КОНТРОЛЬ ОСТАЕТСЯ. Если управление не уходит, блок finally не выполняется! Например, защищенная от попытки область может содержать бесконечный цикл. –

+0

@ Эрик: Я полностью понял этот вопрос из вашего сообщения в блоге. Я также не думал о бесконечном цикле в блоке try/catch – Kredns

0

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