Почему использование Наконец в Попытке … Выгода

ctrl + Shift + R всегда работал для меня. Просто replace all и выберите All Files.

47
задан kemiller2002 20 September 2016 в 17:42
поделиться

13 ответов

Да, это другое. Наконец, всегда будет работать (исключение сбоя программы). Если функция завершается внутри блока try catch или возникает другая ошибка в try или catch, функция finally все равно будет выполняться. Вы не получите эту функциональность, не используя оператор finally.

68
ответ дан 26 November 2019 в 19:32
поделиться

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

Блок finally - это тот, который запускается после завершения блока try. Под завершением я подразумеваю, что он завершается нормально или каким-то образом завершается (выходит из цикла, возвращается из метода, генерирует исключение и т. Д.)

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

0
ответ дан 26 November 2019 в 19:32
поделиться

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

Код в блоке finally четко указывает, что вы выполняете задачи типа завершения для содержимого, содержащегося в try-catch. Думаю, это облегчает чтение.

1
ответ дан 26 November 2019 в 19:32
поделиться

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

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

1
ответ дан 26 November 2019 в 19:32
поделиться

Выполнение очистки в блоке finally должно гарантировать его выполнение. Если блок catch не обрабатывает исключение (т.е. он просто регистрирует его) или даже вызывает другое исключение, код в блоке finally все равно будет выполняться.

1
ответ дан 26 November 2019 в 19:32
поделиться

Блок finally будет выполняться независимо от того, завершился ли функция из-за исключения. (есть некоторые исключения из этого правила, см. этот вопрос о переполнении стека для получения дополнительной информации).

Например:

Try
    'Do something
Catch ex As Exception
    if 'Some Condition
       throw ex
    else
       'Handle exception
Finally
    'Do cleanup
End Try

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

Это хорошая практика, потому что она гарантирует, что ваш код очистки всегда выполняется. Конечно, использование идиомы Resoource Acquisition Is Initialization - гораздо более чистый способ обеспечить очистку ресурсов, но я недостаточно разбираюсь в VB.net, чтобы знать, возможно ли это сделать.

2
ответ дан 26 November 2019 в 19:32
поделиться

Разница в том, что код в блоке try выдает исключение, которое не перехвачено. блоком catch .

Обычно блок catch перехватывает определенный тип исключения и пропускает все остальное. В этом случае,

5
ответ дан 26 November 2019 в 19:32
поделиться

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

3
ответ дан 26 November 2019 в 19:32
поделиться

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

Невозможно выйти из блока try без выполнения его блока finally. Если блок finally существует, он всегда выполняется. (Это утверждение верно для всех намерений и целей. Есть способ выйти из блока try без выполнения блока finally. Если код выполняет System.exit (0); из блока try приложение завершается без команды finally. С другой стороны, если вы отключите машину во время блока попытки, finally тоже не будет выполняться.)

В основном используется для удаления объектов. Будет полезно, когда вы захотите закрыть пользователя определенные ресурсы, такие как файл, открытые ресурсы (db stmts).

Edit

Также окончательно не будут выполняться после исключения stackoverflow.

7
ответ дан 26 November 2019 в 19:32
поделиться

Код с четырьмя переключателями:

  • Вернуть в TRY
  • Вернуть в CATCH
  • Добавить в CATCH
  • Завершить CATCH

     приватная проверка недействительности Окончательно ()
    {
     пытаться
     {
     doFinally ();
     }
     улов
     {
     Console.WriteLine («Последние новости: произошел сбой.»);
     }
    }
    
    частная недействительность doFinally ()
    {
     Console.WriteLine ("");
     Console.Write ("Вот и:" 
     + (radioReturnInTry.Checked? "2. Вернуть при попытке:" 
     : (radioReturnInCatch.Checked? "3. Повторить в catch:"
     : (radioThrowInCatch.Checked? "4. Добавьте улов:"
     : "1. Продолжаем в ловушке:"))));
     пытаться
     {
     если (radioReturnInTry.Checked)
     {
     Console.Write («Возвращение в попытку.»);
     возвращение;
     }
     Console.Write («Меня тошнит при попытке.»);
     выбросить новое исключение («поставить галочку»);
     }
     улов (исключение ex)
     {
     Console.Write ("... поймалча!");
     если (radioReturnInCatch.Checked)
     {
     Console.Write ("Возвращение в улов.");
     возвращение;
     }
     если (radioThrowInCatch.Checked)
     {
     Console.Write («Рвота в ловушке.»);
     выбросить новое исключение («после того, как поймали»);
     }
     }
    наконец {Console.Write ("Наконец-то !!"); }
    Console.WriteLine («Готово !!!»); // перед добавлением чекбокса ThrowInCatch,
     // этого никогда не произойдет (и было отмечено ReSharper серым)
    
    }
    

Вывод:

  • Вот так: 1. Продолжить в ловле: рвота в попытке. ... поймалча! В заключение!! Готово !!!
  • Вот: 2. Возврат в попытку: Возврат в попытку. Наконец !!
  • А вот и: 3. Повтор в улове: рвота в попытке. ... поймалча! Возвращение в улов. В заключение!!
  • Вот и: 4. Вбрасывание улова: Рвота в попытке. ... поймалча! Рвота в улове. В заключение!! Последние новости: произошел сбой.

Подведем итог: Наконец, позаботится о двух вещах:

  1. О коде, который вернул в попытке или в catch.
  2. Или, если у вас было исключение в попытке, И ВЫБРОСЬТЕ исключение в catch,
  3. или, если у вас было исключение в попытке, И НЕ ПОЛУЧИЛО это исключение,

Наконец, чтобы подвести итоги «НАКОНЕЦ» : Наконец, не делает ничего особенного, если вы пытались, и

  1. НЕ ВОЗВРАЩАЕТСЯ,
  2. и обнаруживает любые исключения во время испытания, а затем
  3. НЕ ВОЗВРАЩАЕТСЯ и в улове, и
  4. НЕ БРОСАЕТ или не имеет кода, который выкидывает.

И последнее, но не минимум (наконец): Если у вас есть исключение в вашем коде, которое ВЫ НЕ УЗНАЛИ, ваш код будет летать, НЕ ДОСТУПЯ НА КОНЕЧНО.

Надеюсь, это ясно. (Теперь это для меня ...)

Моше

12
ответ дан 26 November 2019 в 19:32
поделиться

Насколько я помню, я никогда не использовал блок try / catch / finally в моем .NET-коде.

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

Таким образом, на среднем уровне вы чаще будете видеть try / finally (или "using" оператор), чтобы очистить ресурсы. И в try / catch в обработчике верхнего уровня на уровне представления.

В редких случаях, когда мне нужно как перехватить исключение, так и выполнить некоторую очистку, я бы предпочел провести рефакторинг, чтобы следующее:

try
{
    ... do something
}
catch
{
   ... handle exception
}
finally
{
   ... cleanup
}

стало :

try
{
    DoSomethingAndCleanup();
}
catch
{
   ... handle exception
}

...
private void DoSomethingAndCleanup()
{
    try
    {
        ... do something
    }
    finally
    {
        ... cleanup
    }
}

IMHO это намного чище.

1
ответ дан 26 November 2019 в 19:32
поделиться

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

На этот вопрос невозможно ответить полностью, не зная код, о котором идет речь.

Причина в том, что не весь код можно поместить в блок finally. Например, операторы yield не допускаются в блоках finally (и catch). В блоке try может быть несколько ветвей выполнения, некоторые из которых возвращаются, а некоторые нет. Во всех этих случаях выполняется finally, тогда как в примере без finally этого не было бы для кода очистки. Более того, вы не можете перейти (goto) в блок finally, хотя очень редко вы можете перейти к коду после блока catch. Вы также не можете вернуться из блока finally.

Есть довольно много, хотя и очень редких случаев, когда ответ зависит от фактического кода.

0
ответ дан 26 November 2019 в 19:32
поделиться

Я часто использую (я инкапсулировал это в аспект, но это то, из чего я получил аспект):

public static DoLengthyProcessing(this Control control, Action<Control> action)
{
    Cursor oldCursor = control.Cursor
    try
    {
        control.Cursor = Cursors.WaitCursor;
        action(control);
    }
    catch (Exception ex)
    {
        ErrorHandler.Current.Handler(ex);
    }
    finally
    {
        control.Cursor = oldCursor;
    }
}

Или используйте AOP ( как я).

0
ответ дан 26 November 2019 в 19:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: