lec
.pdfКонструкторы (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