Domnin_Lab_9-12 / ЛАБ_12_C# / ИСКЛЮЧИТЕЛЬНЫЕ СИТУАЦИИ И ИХ ОБРАБОТКА
.doc
// Демонстрируем использование объекта-массива ra2. 90
Console.WriteLine(" Длинна массива ra2 -6 ( 91 ) : " + ra2.Length);
for(int i = 1; i <= 10; i++)
ra2[i] = i;
Console.Write(" Содержимое массива ra2 -7 ( >90 ) : ");
for(int i = 1; i <= 10; i++)
Console.Write(ra2[i] + " ");
Console.WriteLine("\n");
} catch(RangeArrayException exc) {
Console.WriteLine(exc);
}
// Теперь демонстрируем "работу над ошибками"
Console.WriteLine(" Сгенерируем ошибки непопадания в диапазон -8(<107)" );
// Используем неверно заданный конструктор. 107
try {
RangeArray ra3 = new RangeArray (100, -10); // Ошибка!
} catch ( RangeArrayException exc) {
Console.WriteLine(exc);
}
// Используем неверно заданный индекс 115
try {
RangeArray ra3 = new RangeArray(-2, 2);
for(int i = -2; i <= 2; i++)
ra3[i] = i;
Console.Write("\n Cодержимое массива ra3 -9 ( 122 ) : ");
for(int i = -2; i <= 10; i++) // Ошибка непопадание в диапазон 123
Console.Write(ra3[i] + " ");
} catch(RangeArrayException exc) {
Console.WriteLine(exc);
}
Console.WriteLine("\n\n\n ");
}
}
Рис 9.1 Результаты наследования исключений, созданных пользователями
Рис 9.2 Результаты переопределения (закомментирования) метода ToString().
Перехват исключений производных классов
При перехвате исключений базовых и производных классов следует иметь в виду, что catch-инструкции базовых классов всегда перехватываю все инструкции производных классов. Поэтому при необходимости фиксации всех исключений всегда следует вначале перехватывать исключения производных классов и выполнять их необходимую обработку, а только в конце обрабатывать исключения базовых классов.
№ 10
// В начале перехватываются исключения производных классов, а потом базовых
using System;
// Создаем класс исключения
class ExcA : ApplicationException {
public ExcA() : base() {}
public ExcA(string str) : base(str) { }
public override string ToString() {
return Message;
}
}
// Cоздаем класс исключения как производный от класса ExcA. 14
class ExcB : ExcA {
public ExcB() : base() { }
public ExcB(string str) : base(str) { }
public override string ToString() {
return Message;
}
}
class OrderMatters {
public static void Main() {
Console.WriteLine(" ");
for(int x=0; x <3; x++) {
try {
if(x==0) throw new ExcA(" Перехват исключение типа ExcA.");
else if(x==1)throw new ExcB(" Перехват исключения типа ExcB.");
else throw new Exception();
}
catch (ExcB exc) {
// Перехватываем исключение 34
Console.WriteLine(exc);
}
catch(ExcA exc) {
// Перехватываем исключение 38
Console.WriteLine(exc);
}
catch(Exception exc) {
Console.WriteLine(exc);
}
}
Console.WriteLine("\n\n\n ");
}
}
Рис 10 Порядок выполнения производных и базовых исключений
Из текста программы следует, что наибольшим приоритетом обработки обладают исключения класса Application Exception, из него выхлдит класс ExcA и самым низким приоритетом обладает класс ExcB. Поэтому в тексте программы приведено единственно верное размещение catch-блоков, при котором все имеющиеся исключения перехватываются. Любое другое размещение порядка срабатывания catch-блоков приведет к пропуску обработки исключений.
Работа с ключевыми словами checked и unchecked
checked – проверенный, unchecked - непроверенный
Данные слова применяются для управления переполнением в результатевыполнения арифметических выражений. Имеют по две формы каждое. Так одна операторная checked-форма – checked ( expr).
Другая проверяет блок иструкций: сhecked {
// Инструкии, подлежащие проверке
}
здесь : expr – контролизуемое выражение
При переполнении генерируется исключение тпа OverflowException.
Две форы для unchecked. Одна – операторная форма, игнорирует переполнение для заданного выражения. Вторая – в блоке инструкций игнорирует переполнение.
unchecked (expr) unchecked {
переполнение игнорируется // Инструкции, для которых переполнение
// игнорируется
}
Здесь: expr – выражение не проверяется на переполнение.
№ 11
// Работа с checked и unchecked
using System;
class checkedD {
public static void Main() {
byte a, b;
byte result;
a = 127;
b = 127;
try {
result = unchecked ((byte)(a * b));
Console.WriteLine("\n Unchecked-результат: " + result);
result = checked((byte)( a* b )); // Это инструкция вызывает исключение
Console.WriteLine(" checked- результат" +
result); // Инструкция не будет выполненна.
}
catch (OverflowException exc) {
// Перехватываем исключение.
Console.WriteLine(exc);
}
Console.WriteLine ( "\n\n\n " );
}
}
Рис 11 Результат непроверяемого выражения усекается
Использование ключевых слов для блоков инструкций
№ 12
// Работа с checked и unchecked для блоков инструкций
using System;
class CheckedBlocks
{
public static void Main()
{
byte a, b;
byte result;
a = 127;
b = 127;
try
{
unchecked
{
a = 127;
b = 127;
result = unchecked((byte)(a * b));
Console.WriteLine("\n Unchecked-результат: " + result);
a = 125;
b = 5;
result = unchecked((byte)(a * b));
Console.WriteLine(" Unchecked-результат: " + result);
}
checked
{
a = 2;
b = 7;
result = checked((byte)(a * b)); // Все в порядке
Console.WriteLine(" checked-результат: " + result);
a = 127;
b = 127;
result = checked((byte)(a * b)); // Здесь должно быть
// сгенеррованно исключение
Console.WriteLine(" checked-результат: " + result);
// Эта инструкция не выполнится
}
}
catch (OverflowException exc)
{
// Перехватываем исключение.
Console.WriteLine(exc);
}
Console.WriteLine("\n\n\n ");
}
}
Рис 12 Использование ключевых слов для блоков с инструкцией
Опции checked/ unchecked могут быть опциями компилятора и тогда есть смысл в программах пользователя задавать статус контроля переполнения.