Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

lec

.pdf
Скачиваний:
25
Добавлен:
24.03.2015
Размер:
3.43 Mб
Скачать

Конструкторы (2 из 4):

1.Инициализирует новый экземпляр класса Exception. public Exception();

2.Инициализирует новый экземпляр класса Exception с заданным сообщением об ошибке.

public Exception (string); [C++] public: Exception(String*);

[JScript] public function Exception(String);

В классе Exception определен ряд свойств:

Message Содержит строку, которая описывает причину ошибки StackTrace Содержит имя класса и метода, вызвавшего исключе-

ние

TargetSite Содержит имя метода, из которого было вызвано исключение

Source Содержит имя программы, вызвавшей исключение HelpLink Строка с любой дополнительной информацией

Методы:

Метод ToString() возвращает строку с описанием исключения.

Пример 1:

 

try

 

{

 

double d = double.Parse(Console.ReadLine());

 

}

 

catch (Exception e)

 

{

 

Console.WriteLine ("Полное описание: "

+ e); //вызов ToString

Console.WriteLine ("Сообщение об ошибке: "

+ e.Message);

Console.WriteLine ("Имя класса и метода: "

+ e.StackTrace);

Console.WriteLine ("Метод: "

+ e.TargetSite);

}

 

Пример 2:

 

public static void Main()

 

{

 

int[ ] а = new int[4];

 

try

 

{

 

for ( int i = 0; i < 10; i++)

 

а[i] = i;

 

}

 

141

catch (IndexOutOfRangeException)

{

Console.WriteLine ("Индекс вне диапазона!"); return;

}

}

Пример 3:

public static void Main()

{

try

{

Class1.Divide(a, b);

}

catch (DivideByZeroException)

{

Console.WriteLine("Делитель равен 0"); b = 1;

}

}

Пример 4.

public static void Main()

{

try

{

double c = double.Parse(Console.ReadLine());

}

catch (Exception e)

{

Console.WriteLine("Error: " + e.Message); return;

}

}

4.Использование нескольких catch-блоков

Сtry-блоком можно связать не один, а несколько catch-блоков.

Однако все catchблоки должны перехватывать исключения различного типа.

using System; class Demo

{

public static void Main()

{

// Здесь массив a длиннее массива b. int[] a = { 4, 8, 10, 32, 64, 128, 256, 512 }; int[] b = { 2, 0, 1, 4, 0, 8 };

142

for (int i = 0; i < a.Length; i++)

{

try

{

Console.WriteLine(a[i] + " / " + b[i] + " равно " + a[i] / b[i]);

}

catch (DivideByZeroException)

{

Console.WriteLine("Деление на ноль!");

}

catch (IndexOutOfRangeException)

{

Console.WriteLine("Выход за границы массива."); return;

}

}

}

}

В общем случае catch-выражения проверяются в том порядке, в котором они встречаются в программе.

Выполняется только инструкция, тип исключения которой совпадает со сгенерированным исключением. Все остальные catch-блоки игнорируются.

catch-блок, предназначенный для "глобального перехвата" должен быть последним в последовательности catch-блоков.

5. Вложение try-блоков

Один try-блок можно вложить в другой. Исключение, сгенерированное во внутреннем try-блоке и не перехваченное catch-инструкцией, которая связана с этим try-блоком, передается во внешний try-блок.

Пример.

В следующей программе исключение типа IndexOutOfRangeException перехватывается не внутренним try-блоком, а внешним.

using System; class Demo

{

public static void Main()

{

// Здесь массив a длиннее массива b. int[] a = { 4, 8, 16, 32, 64, 128, 256, 512 }; int[] b = { 2, 0, 4, 4, 0, 8 };

try

143

{// Внешний try-блок.

for (int i = 0; i < a.Length; i++)

{

try

{// Вложенный try-блок.

Console.WriteLine (a[i] + " / " + b[i] + " = " + a[i] / b[i]);

}

catch (DivideByZeroException)

{

Console.WriteLine ("На ноль делить нельзя!");

}

}

}

catch (IndexOutOfRangeException)

{

Console.WriteLine ("Нет соответствующего элемента."); Console.WriteLine ("Неисправимая ошибка. " +

"Программа завершена.");

return;

}

. . . . . . . . . .

}

}

Исключение, которое может быть обработано внутренним try-блоком (в данном случае это деление на нуль), позволяет программе продолжать работу.

Однако нарушение границ массива перехватывается внешним tryблоком и заставляет программу завершиться.

Внешние try-блоки можно также использовать в качестве механизма "глобального перехвата" для обработки тех ошибок, которые не перехватываются внутренними блоками.

6. Использование блока finally

Возникновение и обработка исключения, как правило, приводит к нетипичному завершению программы. При этом в программе могут остаться

неосвобожденные ресурсы, например, открытые файлы.

Для освобождения ресурсов используют блок finally.

Этот блок должен следовать за блоком try или catch. Последний является необязательным.

Формат: try

{

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

}

catch (ExcepTypel exOb)

{

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

144

}

catch (ExcepType2 exOb)

{

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

}

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

finally

{

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

}

Блок finally будет выполнен в любом случае – было сгенерировано исключение или нет.

Блок finally не может быть определен без блока try. Эта пара (как правило, с блоками catch) может находиться и внутри вызываемого метода.

В одной программе (методе) может быть несколько блоков finally. Все эти блоки будут выполнены после своих try-блоков.

Пример.

public static void Main()

{

try

{

double c = double.Parse(Console.ReadLine());

}

catch (Exception e)

{

Console.WriteLine("Error: " + e.Message); return;

}

finally

{

Console.WriteLine("Здесь освобождаются ресурсы." + "Блок выполняется всегда");

}

}

7. Генерирование исключений вручную

Если пользователь обнаружил в своем методе ошибку, то он может сгенерировать исключение вручную, используя инструкцию throw.

Вызывающая метод программа должна быть готова обработать это исключение.

Формат ее записи таков:

throw exceptOb;

Элемент exceptOb — это объект класса исключений, производного от класса Exception.

throw передает управления в CLR.

145

Пример 1. Генерирование стандартного исключения.

using System;

class Class1

{

public static int Divide (int a, int b)

{

if (b == 0)

throw new DivideByZeroException(); else

return a / b;

}

}

class Demo

{

public static void Main()

{

try

{

Console.WriteLine("a/b=" + Class1.Divide(4, 0));

}

catch (DivideByZeroException)

{

Console.WriteLine("На ноль делить нельзя!");

}

}

}

Пример 2. Генерирование пользовательского исключения.

// Деление пополам числа, которое должно быть четным. using System;

class Class1

{

public static int Divide2(int a)

{

if ( (float)(a / 2) > 0 )

throw new Exception ("Число должно быть четным."); else

return a / 2;

}

}

class Demo

{

public static void Main()

{

146

try

{

Class1.Divide2 (3);

}

catch (Exception e)

{

Console.WriteLine("ERROR: " + e.Message);

}

}

}

8. Повторное генерирование исключений

Исключение, перехваченное одной catch-инструкцией, можно перегенерировать, чтобы обеспечить возможность его перехвата внешней catch-инструкцией.

Самая распространенная причина для повторного генерирования исключения — позволить нескольким обработчикам получить доступ к исключению.

Чтобы повторно сгенерировать исключение, достаточно использовать ключевое слово throw, не указывая исключения.

Пример. using System;

class Class1

{

public static void genException()

{

int[ ] a = { 4, 8, 16, 32, 64, 128, 256, 512 }; int[ ] b = { 2, 0, 4, 4, 0, 8 };

for (int i = 0; i < a.Length; i++)

{

try

{

Console.WriteLine(a[i] + " * " + b[i] + "=" + a[i]*b[i]);

}

catch (IndexOutOfRangeException)

{

Console.WriteLine("Массивы имеют разную длину."); throw; // Генерируем исключение повторно.

}

}

}

}

class Demo

{

public static void Main()

{

try

{

147

Class1.genException();

}

catch (IndexOutOfRangeException)

{

// Перехватываем повторно сгенерированное исключение. Console.WriteLine ("Неисправимая ошибка. "

+ "Программа завершена.");

return;

}

}

}

9.Пользовательские исключения

ВС# имеется возможность обрабатывать исключения, создаваемые программистом.

Для этого достаточно определить класс как производный от класса

Exception или от класса ApplicationException, "родоначальника" иерар-

хии, зарезервированной для исключений, связанных с прикладными программами.

Пример 1.

class MyArrayException1 : ApplicationException

{

HelpLink = "Смотри файл Readme.txt"; Source = "Программа PGM1";

public MyArrayException1 (string Message) : base(Message) { }

}

Пример 2.

class MyArrayException2 : ApplicationException

{

//Реализуем стандартные конструкторы. public MyArrayException2() : base() { }

public MyArrayException2 (string Message) : base(Message) { }

//Переопределяем метод ToString ()

public override string ToString()

{

return Message;

}

}

Пример 3.

class MyArrayException3 : ApplicationException

{

public MyArrayException3()

: base ("Выход за границу массива")

148

{ }

}

Третий пример практически ничего оригинального не вносит, поэтому вместо создания нового класса достаточно использовать существующий, например:

Exception myExc = new Exception ("Выход за границу массива"); throw myExc;

или

throw new Exception ("Выход за границу массива");

или

throw new IndexOutOfRangeException ("Выход за границу массива");

10. Перехват исключений производных классов

Если нужно перехватывать исключения и базового, и производного класса, поместите первой в catch-последовательности инструкцию с заданием производного класса. В противном случае catch-инструкция с заданием базового класса будет перехватывать все исключения производных клаcсов.

//Инструкции перехвата исключений производных классов

//должны стоять перед инструкциями перехвата

//исключений базовых классов.

using System;

class ExceptA : ApplicationException

{

public ExceptA() : base() { }

public ExceptA (string str) : base(str) { }

}

class ExceptB : ExceptA

{

public ExceptB() : base() { }

public ExceptB (string str) : base(str) { }

}

class OrderMatters

{

public 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 (

149

" Исключение типа ExceptB."); else throw new Exception();

}

catch (ExceptB exc)

{

Console.WriteLine(exc);

}

catch (ExceptA exc)

{

Console.WriteLine(exc);

}

catch (Exception exc)

{

Console.WriteLine(exc);

}

}

}

}

11. Использование ключевых слов checked и unchecked

По умолчанию исключение OverflowException не генерируется. С# позволяет управлять генерированием исключений при возникновении переполнения с помощью ключевых слов checked и unchecked, которые должны находиться в try-блоке.

Чтобы указать, что некоторое выражение должно быть проконтролировано на предмет переполнения, используйте ключевое слово checked. А чтобы проигнорировать переполнение, используйте ключевое слово unchecked. В последнем случае результат будет усечен так, чтобы его тип соответствовал типу результата выражения. Режим unchecked действует в настройке среды VS по умолчанию.

Ключевое слово checked имеет две формы. Одна проверяет конкретное выражение и называется операторной checked-формой. Другая же проверяет блок инструкций.

Формат:

checked (выражение)

или checked

{

// Инструкции, подлежащие проверке.

}

Если значение контролируемого выражения переполнилось, генерируется исключение типа OverflowException.

Ключевое слово unchecked имеет две формы. Одна из них — операторная форма, которая позволяет игнорировать переполнение для за-

150

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]