У попередніх уроках, в деяких програмах ми не враховували непередбачені ситуації, які можуть призводити до помилок. Наприклад, коли нам необхідно було ввести число. Якщо замість числа ми ввели б рядок, то при конвертації цього рядка в чисельний тип програма б аварійно завершила роботу, і ми отримали б помилку.
Такі помилки і інші непередбачені ситуації в Сі-шарп називаються винятками. Обробка винятків - це опис реакції програми на подібні події (виключення) під час виконання програми. Реакцією програми може бути коректне завершення роботи програми, виведення інформації про помилку і запит повторення дії (при введенні даних).
Прикладами винятків може бути:
- ділення на нуль;
- Конвертація некоректних даних з одного типу в інший;
- Спроба відкрити файл, якого не існує;
- Доступ до елементу поза рамками масиву;
- Вичерпування пам'яті програми;
- Інше.
Для обробки виключень в Сі-шарп використовується оператор try-catch. Він має таку структуру:
try
{
// блок коду, в якому можливе виключення
}
catch ([тип винятки] [ім'я])
{
// блок коду - обробка виключення
}
Працює це все дуже просто. Виконується код у блоці try, і, якщо в ньому відбувається виключення типу, відповідного типу, зазначеному в catch, то управління передається блоку catch. При цьому, весь код від моменту викидання виключення до кінця блоку try не буде виконано. Після виконання блоку catch, оператор try-catch завершує роботу.
Вказувати ім'я виключення не обов'язково. Виключення представляє собою об'єкт, і до нього ми маємо доступ через це ім'я. З цього об'єкта ми можемо отримати, наприклад, стандартне повідомлення про помилку (Message), або трасування стека (StackTrace), яка допоможе дізнатися місце виникнення помилки. У цьому об'єкті зберігається детальна інформації про виключення.
Якщо тип викинутого виключення не буде відповідати типу, зазначеному в catch - виключення не оброблені, і програма завершить роботу аварійно.
Нижче наведено приклад програми, в якій використовується обробка виключення некоректного формату даних:
static void Main (string [] args)
{
string result = "";
Console.WriteLine ("Введіть число:");
try
{
int a = Convert.ToInt32 (Console.ReadLine ()); // вводимо дані, і конвертуємо в ціле число
result = "Ви ввели число" + a;
}
catch (FormatException)
{
result = "Помилка. Ви ввели не числом";
}
Console.WriteLine (result);
Console.ReadLine ();
}
Типи виключень
Нижче наведені деякі з часто зустрічаються типів винятків.
Exception - базовий тип усіх винятків. Блок catch, в якому зазначено тип Exception буде «ловити» всі винятки.
FormatException - некоректний формат операнда або аргументу (при передачі в метод).
NullReferenceException - У примірнику об'єкта не задане посилання на об'єкт, об'єкт не створений
IndexOutOfRangeException - індекс поза рамками колекції
FileNotFoundException - файл не знайдений.
DivideByZeroException - ділення на нуль
Кілька блоків catch
Одному блоку try може відповідати кілька блоків catch:
try
{
// Блок1
}
catch (FormatException)
{
// блок-обробка виключення 1
}
catch (FileNotFoundException)
{
// блок-обробка виключення 2
}
Залежно від того чи іншого типу виключення в блоці try, виконання буде передане відповідному блоку catch.
Блок finally
Оператор try-catch також може містити блок finally. Особливість блоку finally в тому, що код всередині цього блоку виконається в будь-якому випадку, в незалежності від того, чи було виключення чи ні.
try
{
// Блок1
}
catch (Exception)
{
// обробка виключення
}
finally
{
// блок коду, який виконається обов'язково
}
Виконання коду програми в блоці finally відбувається в останню чергу. Спочатку try потім finally або catch-finally (якщо було виняток).
Зазвичай, він використовується для звільнення ресурсів. Класичним прикладом використання блоку finally є закриття файлу. Навіщо блок finally?
Дуже часто можна почути запитання, для чого потрібен цей блок? Адже, здається, можна звільнити ресурси просто після оператора try-catch, без використання finally. А відповідь дуже проста. Finally гарантує виконання коду, незважаючи ні на що. Навіть якщо в блоках try або catch відбуватиметься вихід з методу за допомогою оператора return - finally виконається.
Оператори try-catch також можуть бути вкладеними. Усередині блоку try небудь catch може бути ще один try-catch.
Обробка винятків, в першу чергу, нам знадобиться при роботі з файлами. Роботі з файлами буде присвячений наступний урок.
Домашнє завдання
Є масив цілих чисел розміром 10. З клавіатури вводиться два числа - порядкові номери елементів масиву, які необхідно підсумовувати. Наприклад, якщо ввели 3 і 5 - підсумовуються третій і 5-й елементи. Потрібно передбачити випадки, коли були введені не числа, і коли одне з чисел, або обидва більше розміру масиву.