До генерирования исключения.
Исключение перехвачено.
После пары операторов try/catch.
Обратите внимание на то, что исключение DivideByZeroException
было сгенерировано с использованием ключевого слова new
в операторе throw
. Не следует забывать, что в данном DivideByZeroException
был автоматически вызван конструктор, используемый по умолчанию, хотя для генерирования исключений доступны и
Исключение, перехваченное в одном блоке catch
, может быть повторно сгенерировано в другом блоке, чтобы быть перехваченным во внешнем блоке catch
. Наиболее вероятной причиной для повторного генерирования исключения служит предоставление доступа к исключению нескольким обработчикам. Допустим, что один обработчик оперирует каким-нибудь одним аспектом исключения, а другой обработчик — другим его аспектом. Для повторного генерирования исключения достаточно указать оператор throw
без сопутствующего выражения, как в приведенной ниже форме.
throw ;
Не следует, однако, забывать, что когда исключение генерируется повторно, то оно не перехватывается снова тем же самым блоком catch
, а передается во внешний блок catch
.
В приведенном ниже примере программы демонстрируется повторное генерирование исключения. В данном случае генерируется исключение IndexOutOfRangeException
.
// Сгенерировать исключение повторно.
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()
.
Использование блока finally
Иногда требуется определить кодовый блок, который будет выполняться после выхода из блока try/catch
. В частности, исключительная ситуация может возникнуть в связи с ошибкой, приводящей к преждевременному возврату из текущего метода. Но в этом методе мог быть открыт файл, который нужно закрыть, или же установлено сетевое соединение, требующее разрывания. Подобные ситуации нередки в программировании, и поэтому для их разрешения в C# предусмотрен удобный способ: воспользоваться блоком finally
.
Для того чтобы указать кодовый блок, который должен выполняться после блока try/catch
, достаточно вставить блок finally
в конце последовательности операторов try/catch
. Ниже приведена общая форма совместного использования блоков try/catch
и finally
.
try {
// Блок кода, предназначенный для обработки ошибок.
}
catch
// Обработчик исключения типа
}
.
.
.
catch (
// Обработчик исключения типа
finally {
// Код завершения обработки исключений.
}