До генерирования исключения.

Исключение перехвачено.

После пары операторов 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().

<p>Использование блока finally </p>

Иногда требуется определить кодовый блок, который будет выполняться после выхода из блока try/catch. В частности, исключительная ситуация может возникнуть в связи с ошибкой, приводящей к преждевременному возврату из текущего метода. Но в этом методе мог быть открыт файл, который нужно закрыть, или же установлено сетевое соединение, требующее разрывания. Подобные ситуации нередки в программировании, и поэтому для их разрешения в C# предусмотрен удобный способ: воспользоваться блоком finally.

Для того чтобы указать кодовый блок, который должен выполняться после блока try/catch, достаточно вставить блок finally в конце последовательности операторов try/catch. Ниже приведена общая форма совместного использования блоков try/catch и finally.

try {

  // Блок кода, предназначенный для обработки ошибок.

}

catch (ExcepTypel exOb) {

  // Обработчик исключения типа ExcepTypel.

}

.

.

.

catch (ЕхсерТуре2 ехОb) {

  // Обработчик исключения типа ЕхсерТуре2. }

finally {

  // Код завершения обработки исключений.

}

Перейти на страницу:

Похожие книги