- •13 Обработка исключительных ситуаций
- •13.1 Класс System.Exception
- •13.2 Основы обработки исключительных ситуаций
- •13.2.1 Применение пары ключевых слов try и catch
- •13.2.2 Простой пример обработки исключительной ситуации
- •13.2.3 Второй пример обработки исключительной ситуации
- •13.3 Последствия неперехвата исключений
- •13.4 Обработка исключительных ситуаций "изящный"
- •13.5 Применение нескольких операторов catch
- •13.6 Перехват всех исключений
- •13.7 Вложение блоков try
- •13.8 Генерирование исключений вручную
- •13.8.1 Повторное генерирование исключений
- •13.9 Использование блока finally
- •13.10 Подробное рассмотрение класса Exception
- •13.10.1 Наиболее часто используемые исключения
- •13.11 Получение производных классов исключений
- •13.12 Перехват исключений производных классов
- •13.13 Применение ключевых слов checked и unchecked
13.4 Обработка исключительных ситуаций "изящный"
способ устранения программных ошибок
Одно из главных преимуществ обработки исключительных ситуаций заключается в том, что она позволяет вовремя отреагировать на ошибку в программе и затем продолжить ее выполнение. В качестве примера рассмотрим еще одну программу, в которой элементы одного массива делятся на элементы другого. Если при этом происходит деление на нуль, то генерируется исключение DivideByZeroException. Обработка подобной исключительной ситуации заключается в том, что программа уведомляет об ошибке и затем продолжает свое выполнение. Таким образом, попытка деления на нуль не приведет к аварийному завершению программы из-за ошибки при ее выполнении. Вместо этого ошибка обрабатывается "изящно", не прерывая выполнение программы.
Листинг 13.5
// Изящно обработать исключительную ситуацию
// и продолжить выполнение программы.
using System;
class ExcDemo3 {
static void Main() {
int[] numer = { 4, 8, 16, 32, 64, 128 };
int[] denom = { 2, 0, 4, 4, 0, 8 };
for(int i=0; i < numer.Length; i++) {
try {
Console.WriteLine(numer[i] + " / " +
denom[i] + " равно " +
numer[i]/denom[i]);
}
catch (DivideByZeroException) {
// Перехватить исключение.
Console.WriteLine("Делить на нуль нельзя!");
}
}
}
}
Ниже приведен результат выполнения этой программы.
4/2 равно 2
Делить на нуль нельзя!
16/4 равно 4
32/4 равно 8
Делить на нуль нельзя!
128 / 8 равно 16
Из данного примера следует еще один важный вывод: как только исключение обработано, оно удаляется из системы. Поэтому в приведенной выше программе проверка ошибок в блоке try начинается снова на каждом шаге цикла for, при условии, что все предыдущие исключительные ситуации были обработаны. Это позволяет обрабатывать в программе повторяющиеся ошибки.
13.5 Применение нескольких операторов catch
С одним оператором try можно связать несколько операторов catch. И на практике это делается довольно часто. Но все операторы catch должны перехватывать исключения разного типа. В качестве примера ниже приведена программа, в которой перехватываются ошибки выхода за границы массива и деления на нуль.
Листинг 13.6
// Использовать несколько операторов catch.
using System;
class ExcDemo4 {
static void Main() {
// Здесь массив numer длиннее массива denom.
int[] numer = { 4, 8, 16, 32, 64, 128, 256, 512 };
int[] denom = { 2, 0, 4, 4, 0, 8 };
for(int i=0; i < numer.Length; i++) {
try {
Console.WriteLine(numer[i] + " / " +
denom[i] + " равно " +
numer[i]/denom[i]);
}
catch (DivideByZeroException) {
Console.WriteLine("Делить на нуль нельзя!");
}
catch (IndexOutOfRangeException) {
Console.WriteLine("Подходящий элемент не найден.");
}
}
}
}
Вот к какому результату приводит выполнение этой программы.
4/2 равно 2
Делить на нуль нельзя!
16/4 равно 4
32/4 равно 8
Делить на нуль нельзя!
128 / 8 равно 16
Подходящий элемент не найден.
Подходящий элемент не найден.
Как следует из приведенного выше результата, каждый оператор catch реагирует только на свой тип исключения.
Вообще говоря, операторы catch выполняются по порядку их следования в программе. Но при этом выполняется только один блок catch, в котором тип исключения совпадает с типом генерируемого исключения. А все остальные блоки catch пропускаются.
