Книга: C# 4.0: полное руководство
Перехват исключений производных классов
Перехват исключений производных классов
При попытке перехватить типы исключений, относящихся как к базовым, так и к производным классам, следует особенно внимательно соблюдать порядок следования операторов catch, поскольку перехват исключения базового класса будет совпадать с перехватом исключений любых его производных классов. Например, класс Exception
является базовым для всех исключений, и поэтому вместе с исключением типа Exception
могут быть перехвачены и все остальные исключения производных от него классов. Конечно, для более четкого перехвата всех исключений можно воспользоваться упоминавшейся ранее формой оператора catch
без указания конкретного типа исключения. Но вопрос перехвата исключений производных классов становится весьма актуальным и в других ситуациях, особенно при создании собственных исключений.
Если требуется перехватывать исключения базового и производного классов, то первым по порядку должен следовать оператор catch
, перехватывающий исключение производного класса. Это правило необходимо соблюдать потому, что при перехвате исключения базового класса будут также перехвачены исключения всех производных от него классов. Правда, это правило соблюдается автоматически: если первым расположить в коде оператор catch
, перехватывающий исключение базового класса, то во время компиляции этого кода будет выдано сообщение об ошибке.
В приведенном ниже примере программы создаются два класса исключений: ExceptA
и ExceptB
. Класс ExceptA
является производным от класса Exception
, а класс ExceptB
— производным от класса ExceptA
. Затем в программе генерируются исключения каждого типа. Ради краткости в классах специальных исключений предоставляется только один конструктор, принимающий символьную строку, описывающую исключение. Но при разработке программ коммерческого назначения в классах специальных исключений обычно требуется предоставлять все четыре конструктора, определяемых в классе Exception
.
// Исключения производных классов должны появляться до
// исключений базового класса.
using System;
// Создать класс исключения,
class ExceptA : Exception {
public ExceptA(string str) : base(str) { }
public override string ToString() {
return Message;
}
}
// Создать класс исключения, производный от класса ExceptA.
class ExceptB : ExceptA {
public ExceptB(string str) : base(str) { }
public override string ToString() {
return Message;
}
}
class OrderMatters {
static void Main() {
for(int x = 0; x < 3; x++) {
try {
if (x==0)
throw new ExceptA("Перехват исключения типа ExceptA");
else if(x==1)
throw new ExceptB("Перехват исключения типа ExceptB");
else
throw new Exception();
}
catch (ExceptB exc) {
Console.WriteLine(exc);
}
catch (ExceptA exc) {
Console.WriteLine(exc);
}
catch (Exception exc) {
Console.WriteLine(exc);
}
}
}
}
Вот к какому результату приводит выполнение этой программы.
Перехват исключения типа ExceptA.
Перехват исключения типа ExceptB.
System.Exception: Выдано исключение типа "System.Exception".
в OrderMatters.Main() в <имя_файла>:строка 36
Обратите внимание на порядок следования операторов catch
. Именно в таком порядке они и должны выполняться. Класс ExceptB
является производным от класса ExceptA
, поэтому исключение типа ExceptB
должно перехватываться до исключения типа ExceptA.
Аналогично, исключение типа Exception (т.е. базового класса для всех исключений) должно перехватываться последним. Для того чтобы убедиться в этом, измените порядок следования операторов catch. В итоге это приведет к ошибке во время компиляции.
Полезным примером использования оператора catch
, перехватывающего исключения базового класса, служит перехват всей категории исключений. Допустим, что создается ряд исключений для управления некоторым устройством. Если сделать их классы производными от общего базового класса, то в тех приложениях, где необязательно выяснять конкретную причину возникшей ошибки, достаточно перехватывать исключение базового класса и тем самым исключить ненужное дублирование кода.
- Класс System.Exception
- Основы обработки исключительных ситуаций
- Последствия неперехвата исключений
- Обработка исключительных ситуаций - “изящный” способ устранения программных ошибок
- Применение нескольких операторов catch
- Перехват всех исключений
- Вложение блоков try
- Генерирование исключений вручную
- Использование блока finally
- Подробное рассмотрение класса Exception
- Получение производных классов исключений
- Перехват исключений производных классов
- Применение ключевых слов checked и unchecked
- Перехват всех исключений
- Перехват ошибок
- Генерирование исключений
- ГЛАВА 4 Обработка исключений
- ГЛАВА 6. Структурированная обработка исключений
- Исключения и обработчики исключений
- 9.7.4. Иерархии классов и абстрактные классы
- 10.7.1. Перехват соединения
- 14.5.4. Перехват соединения
- 10.6.4. Перехват сигналов: sigaction()
- 8.8.5. Шаг 4. Задание интерфейсов классов
- Векторная обработка исключений