Що б там не було, нарешті, блоки виконуються (майже) завжди, тож яка різниця між тим, що вкладати в нього код або залишати його незакритим?
Що б там не було, нарешті, блоки виконуються (майже) завжди, тож яка різниця між тим, що вкладати в нього код або залишати його незакритим?
Відповіді:
Код всередині остаточного блоку буде виконуватися незалежно від того, існує чи ні. Це дуже зручно, коли справа стосується певних функцій побутової роботи, які потрібно завжди виконувати, як з'єднання для закриття.
Тепер я здогадуюсь, що ваше питання - чому ви повинні робити це:
try
{
doSomething();
}
catch
{
catchSomething();
}
finally
{
alwaysDoThis();
}
Коли ви можете це зробити:
try
{
doSomething();
}
catch
{
catchSomething();
}
alwaysDoThis();
Відповідь полягає в тому, що багато разів код всередині вашої заяви про вилов або повторно скине виняток, або вирветься з поточної функції. З останнім кодом, "alwaysDoThis ();" виклик не виконуватиметься, якщо код всередині оператора вилову повертає або викидає новий виняток.
Більшість переваг використання спробу-нарешті вже було вказано, але я подумав, що додам це:
try
{
// Code here that might throw an exception...
if (arbitraryCondition)
{
return true;
}
// Code here that might throw an exception...
}
finally
{
// Code here gets executed regardless of whether "return true;" was called within the try block (i.e. regardless of the value of arbitraryCondition).
}
Така поведінка робить її дуже корисною в різних ситуаціях, особливо, коли вам потрібно проводити очищення (розпоряджатися ресурсами), хоча блок використання в цьому випадку часто краще.
будь-який час, коли ви використовуєте керовані запити коду, такі як зчитувачі потоків, запити db тощо; і ви хочете зловити виняток, тоді використовуйте спробуйте catch нарешті та закрийте потік, зчитувач даних тощо, нарешті, якщо ви цього не зробите, коли з’єднання не закривається, це справді погано із запитами db
SqlConnection myConn = new SqlConnection("Connectionstring");
try
{
myConn.Open();
//make na DB Request
}
catch (Exception DBException)
{
//do somehting with exception
}
finally
{
myConn.Close();
myConn.Dispose();
}
якщо ви не хочете виявити помилку, тоді використовуйте
using (SqlConnection myConn = new SqlConnection("Connectionstring"))
{
myConn.Open();
//make na DB Request
myConn.Close();
}
і об’єкт з'єднання буде видалено автоматично, якщо є помилка, але ви не зафіксували помилку
Тому що, нарешті, буде виконано, навіть якщо ви не обробляєте виняток у блоці улов.
Нарешті, заяви можна виконати навіть після повернення.
private int myfun()
{
int a = 100; //any number
int b = 0;
try
{
a = (5 / b);
return a;
}
catch (Exception ex)
{
Response.Write(ex.Message);
return a;
}
// Response.Write("Statement after return before finally"); -->this will give error "Syntax error, 'try' expected"
finally
{
Response.Write("Statement after return in finally"); // --> This will execute , even after having return code above
}
Response.Write("Statement after return after finally"); // -->Unreachable code
}
finally
, а саме:
try {
// do something risky
} catch (Exception ex) {
// handle an exception
} finally {
// do any required cleanup
}
- це гарантована можливість виконання коду після вашого try..catch
блоку, незалежно від того, чи викинув випробувальний блок виняток.
Це робить його ідеальним для таких речей, як звільнення ресурсів, db-з'єднання, ручки файлів тощо.
я поясню використання, нарешті, з прикладом виключення з читання файлів
try{ StreamReader strReader = new StreamReader(@"C:\Ariven\Project\Data.txt"); Console.WriteLine(strReader.ReadeToEnd()); StreamReader.Close(); } catch (Exception ex) { Console.WriteLine(ex.Message); }
у наведеному вище прикладі, якщо файл під назвою Data.txt відсутній, буде викинуто виняток і буде оброблятися, але викликане твердженняStreamReader.Close();
ніколи не буде виконано.
Через це ресурси, пов'язані з читачем, ніколи не виходили.
StreamReader strReader = null; try{ strReader = new StreamReader(@"C:\Ariven\Project\Data.txt"); Console.WriteLine(strReader.ReadeToEnd()); } catch (Exception ex){ Console.WriteLine(ex.Message); } finally{ if (strReader != null){ StreamReader.Close(); } }
Щасливе кодування :)
Примітка: "@" використовується для створення дослівного рядка, щоб уникнути помилки "Нерозпізнаної послідовності відходу". Символ @ означає читати цей рядок буквально, а не інтерпретувати контрольні символи інакше.
Скажімо, потрібно повернути курсор до вказівника за замовчуванням замість курсора очікування (пісочного годинника). Якщо перед встановленням курсору буде викинуто виняток, і програма не завершить аварійне завершення роботи, ви можете залишити заплутаний курсор.
Іноді ви не хочете обробляти виняток (немає блоку захоплення), але хочете виконати якийсь код очищення.
Наприклад:
try
{
// exception (or not)
}
finally
{
// clean up always
}
Зрештою, блок цінний для очищення будь-яких ресурсів, виділених у блоці спробу, а також для запуску будь-якого коду, який потрібно виконати, навіть якщо є виняток. Контроль завжди передається остаточному блоку, незалежно від того, як виходить блок спробу.
А-а ... я думаю, я бачу, що ти кажеш! Зайняв мене на секунду ... Вам цікаво, "чому розмістити його в остаточному блоці замість того, щоб після остаточно блокувати і зовсім поза межами" пробувати-нарешті ".
Наприклад, це може бути тому, що ви зупиняєте виконання, якщо ви кидаєте помилку, але все одно хочете очистити ресурси, наприклад, відкриті файли, підключення до бази даних тощо.
Контрольний потік остаточного блоку здійснюється або після блоку "Спробувати" або "Зловити".
[1. First Code]
[2. Try]
[3. Catch]
[4. Finally]
[5. After Code]
за винятком 1> 2> 3> 4> 5, якщо 3 має оператор Return 1> 2> 3> 4
без винятку 1> 2> 4> 5, якщо 2 має вираз повернення 1> 2> 4
Як зазначено в документації :
Загальне використання улову і, нарешті, разом - це отримання та використання ресурсів у пробному блоці, вирішення виняткових обставин у блоці вилову та звільнення ресурсів у остаточному блоці.
Варто також прочитати це , де зазначено:
Після того, як буде знайдено відповідне застереження щодо вилову, система готується передати управління першому оператору застереження про вилов. Перед тим, як розпочнеться виконання застереження, система спочатку виконує для того, щоб будь-які остаточні пропозиції, які були пов'язані з операторами спробу, вклали більше, ніж ті, що вивели виняток.
Тож зрозуміло, що код, який знаходиться в finally
пункті, буде виконуватися, навіть якщо попередній catch
пункт мав return
заяву.