- •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.8 Генерирование исключений вручную
В приведенных выше примерах перехватывались исключения, генерировавшиеся исполняющей системой автоматически. Но исключение может быть сгенерировано и вручную с помощью оператора throw. Ниже приведена общая форма такого генерирования:
throw exceptOb;
где в качестве exceptOb должен быть обозначен объект класса исключений, производного от класса Exception.
Ниже приведен пример программы, в которой демонстрируется применение оператора throw для генерирования исключения DivideByZeroException.
Листинг 13.9
// Сгенерировать исключение вручную.
using System;
class ThrowDemo
{
static void Main()
{
try {
Console.WriteLine("До генерирования исключения.");
throw new DivideByZeroException();
}
catch (DivideByZeroException) {
Console.WriteLine("Исключение перехвачено.");
}
Console.WriteLine("После пары операторов try/catch.");
}
}
Вот к какому результату приводит выполнение этой программы.
До генерирования исключения.
Исключение перехвачено.
После пары операторов try/catch.
Обратите внимание на то, что исключение DivideByZeroException было сгенерировано с использованием ключевого слова new в операторе throw. Не следует забывать, что в данном случае генерируется конкретный объект, а следовательно, он должен быть создан перед генерированием исключения. Это означает, что сгенерировать исключение только по его типу нельзя. В данном примере для создания объекта DivideByZeroException был автоматически вызван конструктор, используемый по умолчанию, хотя для генерирования исключений доступны и другие конструкторы.
13.8.1 Повторное генерирование исключений
Исключение, перехваченное в одном блоке catch, может быть повторно сгенерировано в другом блоке, чтобы быть перехваченным во внешнем блоке catch. Наиболее вероятной причиной для повторного генерирования исключения служит предоставление доступа к исключению нескольким обработчикам. Допустим, что один обработчик оперирует каким-нибудь одним аспектом исключения, а другой обработчик другим его аспектом. Для повторного генерирования исключения достаточно указать оператор throw без сопутствующего выражения, как в приведенной ниже форме.
throw ;
Не следует, однако, забывать, что когда исключение генерируется повторно, то оно не перехватывается снова тем же самым блоком catch, а передается во внешний блок catch.
В приведенном ниже примере программы демонстрируется повторное генерирование исключения. В данном случае генерируется исключение IndexOutOfRangeException.
Листинг 13.10
// Сгенерировать исключение повторно.
using System;
class Rethrow
{
public static void GenException()
{
// Здесь массив 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("Подходящий элемент не найден.");
throw; // сгенерировать исключение повторно
}
}
}
}
class RethrowDemo
{
static void Main()
{
try {
Rethrow.GenException();
}
catch(IndexOutOfRangeException)
{
// перехватить исключение повторно
Console.WriteLine("Неисправимая ошибка - " +
"программа прервана.");
}
}
}
В этом примере программы ошибки из-за деления на нуль обрабатываются локально в методе GenException(), но ошибка выхода за границы массива генерируется повторно. В данном случае исключение IndexOutOfRangeException обрабатывается в методе Main().
