Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Podbelsky_V_V_C_Bazovy_kurs.pdf
Скачиваний:
83
Добавлен:
02.06.2015
Размер:
1.73 Mб
Скачать

334

Г л а в а 1 6

 

 

16.6. Генерация исключений

Об обработке исключений, посылаемых методами библиотечных классов, мы уже говорили и неоднократно этим пользовались. Чтобы глубже разобраться в механизме генерации исключений и научиться создавать и посылать исключения в любой заранее предусмотренной ситуации, возникшей при выполнении программы, нужно ясно понять и усвоить, что исключения – это объекты некоторых специальных классов. Все системные классы исключений являются производными от класса System.Exception. Этот класс имеет несколько замечательных свойств, два из которых (Message и Sourse) мы уже применяли. При создании объектов классов исключений наиболее важными являются Message и InnerException. Оба эти свойства в обязательном порядке используются всеми исключениями. Они предназначены только для чтения.

●●Message – это свойство типа String, значение которого представляет собой текст сообщения о причине возникновения исключения;

●●InnerException – имеет тип Exception и представляет собой ненулевую ссылку на то исключение, которое является причиной возникновения данного исключения.

Значения этих свойств можно задать с помощью параметров конструктора при создании объекта класса System.Exception. Нам могут быть полезны следующие конструкторы:

●●Exception() – инициализирует умалчиваемыми данными новый экземпляр класса Exception;

●●Exception(String) – инициализирует новое исключение (новый объект). Параметр задает значение свойства Message;

●●Exception(String, Exception) – параметр типа String определяет значение свойства Message, а второй параметр представляет собой ссылку на внутреннее исключение, которое явилось причиной данного исключения.

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

Исключения

335

 

 

Для генерации (для посылки) исключения из выбранной точки кода программы используется оператор, имеющий одну из следующих двух форм:

throw выражение; throw;

Оператор throw без выражения; можно использовать только в catch-блоке для ретрансляции исключения в catch-блок следующего уровня.

Значением выражения, использованного в операторе throw, должна быть ссылка на объект класса исключений. Именно этот объект посылается в качестве исключения. Если значение выражения равно null, то вместо него посылается исключение System.NullReferenceException.

Одной из наиболее важных задач, решаемых с применением исключений, является проверка корректности данных, получаемых программой или отдельным методом. Мы уже показали на нескольких примерах как использовать исключения, автоматически формируемые при чтении данных от клавиатуры.

В следующей программе продемонстрируем как программировать генерацию исключений. Пусть требуется вычислить значение электрической мощности, рассеиваемой на сопротивлении в 100 Ом при включении его в сеть с напряжением 110 или 127 или 220 вольт. Пользователь может ввести только одно из указанных значений напряжения. Ошибаться при вводе можно только два раза. При третьей ошибке программа должна завершить работу без вычисления мощности.

Ошибки ввода в данном случае могут быть двух видов – лексические и семантические. Лексическая ошибка – это неверная запись вещественного числа при его наборе на клавиатуре. Семантическая ошибка – отличие введенного числа от трех допустимых условием задачи значений (110, 127, 220). Для преобразования введенной с клавиатуры последовательности символов в числовое значение применим метод TryParse(). Тогда послать исключение при лексической ошибке можно с помощью следующих операторов:

string input = Console.ReadLine(); if (!double.TryParse(input, out U))

throw new Exception("Ошибка в формате данных!");

336

Г л а в а 1 6

 

 

В данном фрагменте U – имя переменной типа double, которая будет представлять в программе введенное пользователем значение напряжения.

Для генерации исключения при семантической ошибки используем такой код:

if (U != 110 & U != 127 & U != 220)

throw new Exception(input+" - недопустимое значение!");

Все приведенные операторы разместим в try-блоке, вслед за которым поместим обработчик исключений (catch-блок), где будем подсчитывать их количество. Всю конструкцию try/catch поместим в цикл. Тем, кто забыл раздел физики, посвященный электричеству, напомним, что мощность, потребляемая сопротивлением R при его включении в сеть с напряжением U, вычисляется по формуле U2/R. Программа в целом может быть такой:

// 16_05.cs исключения для проверки вводимых

//данных using System;

class Program { static void Main() {

double U, R=100;

int counter = 0; // Счетчик исключений while (true) {

Console.Write("Введите напряжение (110, 127, 220): ");

try

{

string input = Console.ReadLine(); if (!double.TryParse(input, out U))

throw new Exception("Ошибка в формате данных!");

if (U != 110 & U != 127 & U != 220)

throw new Exception(input+" - недопустимое значение!");

}

catch (Exception ex)

{

Console.WriteLine(ex.Message); if (counter++ >= 2)

Исключения

337

 

 

{ Console.WriteLine("Трижды ошиблись!");

return; } continue;

}

break;

}// end of while

Console.WriteLine("Потребляемая мощность: {0,5:f}", U*U/R);

}

}

Результат выполнения программы:

* Первый сеанс:

Введите напряжение (110, 127, 220): 120<ENTER> 120 - недопустимое значение!

Введите напряжение (110, 127, 220): 110f<ENTER>

Ошибка в формате данных!

Введите напряжение (110, 127, 220): asd<ENTER>

Ошибка в формате данных! Трижды ошиблись!

* Второй сеанс:

Введите напряжение (110, 127, 220): 127<ENTER>

Потребляемая мощность: 161,29

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

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

static double scalar(double[ ]x, double[ ]y) { if(x.Length!=y.Length)

throw new Exception("Неверные размеры векторов!");

338

Г л а в а 1 6

 

 

Обработку исключений, формируемых методом при ошибке в его аргументах, обычно выполняют в коде, из которого выполнено обращение к методу. (Там, где заданы конкретные аргументы.) В следующей программе обращения к методу scalar() размещены в try-блоке. Первое обращение корректно, во втором допущена ошибка – размеры массивов-аргументов не совпадают. Текст программы:

// 16_06.cs исключения в теле метода using System;

class Program {

static double scalar(double[] x, double[] y) { if (x.Length != y.Length)

throw new Exception("Неверные размеры векторов!");

double result = 0;

for (int i = 0; i < x.Length; i++) result += x[i] * y[i];

return Math.Sqrt(result);

}

static void Main()

{

try { Console.WriteLine(«scalar1=»+

scalar(new double[] {1,2,3,4}, new double[] {1,2,3,4}));

Console.WriteLine(«scalar2=»+

scalar(new double[] {1,2,3,4}, new double[] {1,2,3}));

}

catch (Exception ex){ Console.WriteLine(ex.Message);

}

}

}

Результат выполнения программы:

Исключения

339

 

 

16.7. Пользовательские классы исключений

Впредыдущих программах при генерации исключений был использован системный тип Exception. Кроме него в среде .NET имеется большое количество специализированных классов исключений. Часто этих системных исключений вполне достаточно для реакции на те события, которые могут произойти в вашей программе. Однако программист-пользователь может определять собственные классы исключений. Их можно создавать либо на базе класса Exception, либо используя в качестве базовых более специализированные системные классы исключений.

Встандартной библиотеке определены два класса исключений, каждый из которых является прямым наследником класса System.Exception. Класс System.SystemException соответствует исключениям, порождаемым средой, в которой выполняется прикладная программа. Класс System.ApplicationException пред-

назначен для создания объектов-исключений, относящихся к выполнению прикладных программ. Создавая собственные классы исключений, стандарт языка C# рекомендует делать их наследниками класса System.ApplicationException, а не класса System.Exception.

Определяя собственный класс исключений, рекомендуется объявить в этом классе три конструктора: конструктор умолчания, конструктор с параметрами типа string и конструктор с параметрами string и Exception. В каждом из этих конструкторов нужно вызвать конструкторы базового класса. В конструкторе умолчания в обращении к базовому конструктору ему передается текст сообщения, уникального для собственного класса исключений. В конструкторе с параметром типа string базовому конструктору передается сообщение об ошибке. В третьем конструкторе базовому конструктору передается сообщение об ошибке и объект внутреннего исключения.

Контрольные вопросы

scalar1=5,47722557505166

Неверные размеры векторов! 1. Что такое исключение?

2. В чём различия синхронных и асинхронных ситуаций?

3. Для обработки каких ситуаций применяется механизм исключений?

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