
Обработка исключений.pptx
- Количество слайдов: 32
Обработка исключений Конструирование программ и языки программирования
Не всегда ошибки случаются по вине того, кто кодирует приложение. Иногда приложение генерирует ошибку из-за действий конечного пользователя, или же ошибка вызвана контекстом среды, в которой выполняется код. В любом случае вы всегда должны ожидать возникновения ошибок в своих приложениях и проводить кодирование в соответствии с этими ожиданиями. В . NET Framework предусмотрена развитая система обработки ошибок. Механизм обработки ошибок C# позволяет закодировать пользовательскую обработку для каждого типа ошибочных условий, а также отделить код, потенциально порождающий ошибки, от кода, обрабатывающего их.
Программные ошибки (bugs) Так обычно называются ошибки, которые допускает программист. Например, предположим, что приложение создается с помощью неуправляемого языка С++. Если динамически выделяемая память не освобождается, что чревато утечкой памяти, появляется программная ошибка.
Пользовательские ошибки (user errors) В отличие от программных ошибок, пользовательские ошибки обычно возникают из-за тех, кто запускает приложение, а не тех, кто его создает. Например, ввод конечным пользователем в текстовом поле неправильно оформленной строки может привести к генерации ошибки подобного рода, если в коде не была предусмотрена возможность обработки некорректного ввода.
Исключения (exceptions) Исключениями, или исключительными ситуациями, обычно называются аномалии, которые могут возникать во время выполнения и которые трудно, а порой и вообще невозможно, предусмотреть во время программирования приложения. К числу таких возможных исключений относятся: попытки подключения к базе данных, которой больше не существует, попытки открытия поврежденного файла попытки установки связи с машиной, которая в текущий момент находится в автономном режиме. В каждом из этих случаев программист (и конечный пользователь) мало что может сделать с подобными "исключительными" обстоятельствами.
Обработка ошибок Возможные действия при ошибке: прервать выполнение программы; возвратить значение, означающее «ошибка» ; вывести сообщение об ошибке и вернуть вызывающей программе некоторое приемлемое значение, которое позволит ей продолжать работу; выбросить исключение. Исключения генерирует либо система выполнения, либо программист с помощью оператора throw. 6
Простая проверка ввода // пример проверки формата вводимого значения: double a; if (! double. Try. Parse(Console. Read. Line(), out a) ) {Console. Write. Line(" Неверный формат "); return; } // при вводе более одного значения предпочтительнее // использовать механизм исключений // пример проверки допустимости значения: double a = double. Parse(Console. Read. Line()); . . . if ( a <= 0 ) { Console. Write. Line("Неверное значение (<= 0)" ); return; } 7
Проверка ввода с помощью цикла do-while using System; namespace Console. Application 1 { class Program { static void Main() { const int max_attempts = 3; int i = 0; do { Console. Write. Line( "Введите значение > 0: " ); double a = double. Parse(Console. Read. Line()); ++i; if ( i >= max_attempts ) { } while ( a <= 0 ); … return; } } } // ограничивать кол-во попыток обязательно! } 8
Рекомендуемая структура обработки ошибок исходных данных ввод данных ошибка 1? ошибка 2? да да сообщение 1 выход сообщение 2 выход . . . основной поток вычислений 9
Обработка исключений Исключительная ситуация, или исключение — это возникновение непредвиденного или аварийного события, которое может порождаться некорректным использованием аппаратуры. Например, это деление на ноль или обращение по несуществующему адресу памяти. Исключения позволяют логически разделить вычислительный процесс на две части — обнаружение аварийной ситуации и ее обработка. 10
Некоторые стандартные исключения Имя Пояснение Arithmetic. Exception Ошибка в арифметических операциях или преобразованиях (является предком Divide. Be. Zero. Exception и Over. Flow. Exception) Divide. By. Zero. Excepti on Попытка деления на ноль Format. Exception Попытка передать в метод аргумент неверного формата Index. Out. Of. Range. Exc Индекс массива выходит за границы диапазона eption Invalid. Cast. Exception Ошибка преобразования типа Out. Of. Memory. Except Недостаточно памяти для создания нового объекта ion Over. Flow. Exception Переполнение при выполнении арифметических операций 11
Составляющие процесса обработки исключений в. NET Программирование со структурированной обработкой исключений подразумевает использование четырех следующих связанных между собой сущностей: • тип класса, который представляет детали исключения; • член, способный генерировать (throw) в вызывающем коде экземпляр класса исключения при соответствующих обстоятельствах; • блок кода на вызывающей стороне, ответственный за обращение к члену, в котором может произойти исключение; • блок кода на вызывающей стороне, который будет обрабатывать (или перехватывать (catch)) исключение в случае его возникновения.
Синтаксис исключения try { // Блок кода, предназначенный для обработки ошибок. } catch (Excep. Typel ex. Ob) { // Обработчик исключения типа Excep. Typel } catch (Excep. Type 2 ex. Ob) { // Обработчик исключения типа Ехсер. Type 2. } finally { // Код завершения обработки исключений. }
Оператор try Служит для обнаружения и обработки исключений. Оператор содержит три части: контролируемый блок — составной оператор, предваряемый ключевым словом try. В контролируемый блок включаются потенциально опасные операторы программы. Все функции, прямо или косвенно вызываемые из блока, также считаются ему принадлежащими; один или несколько обработчиков исключений — блоков catch, в которых описывается, как обрабатываются ошибки различных типов; блок завершения finally, выполняемый независимо от того, возникла ли ошибка в контролируемом блоке. Синтаксис оператора try: try блок [ catch-блоки ] [ finally-блок ] 14
Механизм обработки исключений Функция или операция, в которой возникла ошибка, генерируют исключение; Выполнение текущего блока прекращается, отыскивается соответствующий обработчик исключения, ему передается управление. В любом случае (была ошибка или нет) выполняется блок finally, если он присутствует. Если обработчик не найден, вызывается стандартный обработчик исключения. 15
Пример 1: try { // Контролируемый блок } catch ( Overflow. Exception e ) { // Обработка переполнения } catch ( Divide. By. Zero. Exception ) { // Обработка деления на 0 } catch { // Обработка всех остальных исключений } 16
Блок try Иллюстрация генерации исключения что-нибудь вызов метода что-нибудь еще Блоки catch обработчик 1 обработчик 2 … обработчик всех что-нибудь вызов другого метода что-нибудь еще . . . АААА!!! генерация исключения п о и с к 17
Пример 2: проверка ввода if (u < 0) static void Main() { { Console. Write. Line( "Недопустимое …" ); try return; } { Console. Write. Line( "Введите напряжение: " ); double u = double. Parse( Console. Read. Line() ); Console. Write. Line( "Введите сопротивление: " ); double r = double. Parse(Console. Read. Line() ); double i = u / r; Console. Write. Line( "Сила тока - " + i ); } catch ( Format. Exception ) { Console. Write. Line( "Неверный формат ввода!" ); } catch // общий случай { Console. Write. Line( "Неопознанное исключение" ); } } 18
Оператор throw [ выражение ]; Чтобы сообщить о выполнении исключительных ситуаций в программе, можно использовать оператор throw. То есть с помощью этого оператора мы сами можем создать исключение и вызвать его в процессе выполнения. Параметр должен быть объектом, порожденным от стандартного класса System. Exception. Этот объект используется для передачи информации об исключении его обработчику. Пример: throw new Divide. By. Zero. Exception(); 19
в программе происходит ввод строки, если длина строки будет больше 6 символов, возникает исключение static void Main(string[] args) { try { string message = Console. Read. Line(); if (message. Length > 6) { throw new Exception("Длина сроки больше 6 символов"); } } catch (Exception e) { Console. Write. Line("Ошибка: " + e. Message); } Console. Read. Line
Обработка исключений является удобным способом предотвращения аварийного завершения программы в случае попытки выполнения каких-либо некорректных действий. Когда же в программе требуется предусмотреть возможность появления различных по типу и обработке исключительных ситуаций, использовать один класс Exception и соответствующий ему обработчик catch становится неудобным, так как обработчик должен включать в себя все возможные обработки исключительных ситуаций.
Пример ситуации При работе с матрицами исключительные ситуации могут возникнуть в случаях, когда: · конструктор получает неположительные значения количества строк или столбцов; · происходит обращение к элементу матрицы по некорректным индексам; · при выполнении операции сложения размеры двух матриц не совпадают; · при выполнении операции умножения количество столбцов первой матрицы не совпадает с количеством строк второй матрицы; · при вычислении обратной матрицы исходная матрица оказывается вырожденной. Если во всех этих случаях пользователю необходимо показать только сообщение об ошибке и прервать выполнение блока try, то достаточно использовать только стандартное исключение Exception, передав в его поле Message необходимое сообщение. Однако если требуется более сложная обработка ошибки, – например, корректировка данных, приведение матриц к определенному виду и повторное выполнение операции, вызвавшей исключение – единый обработчик будет сложным и неудобным:
try { // код, в котором могут возникнуть исключения с матрицами } catch (Exception e) { if (e. Message. Equals("Summ")) { // действия по обработке ситуации, когда нельзя // сложить две матрицы . . . } if (e. Message. Equals("Product")) { // действия по обработке ситуации, когда нельзя // умножить две матрицы . . . } // обработка других исключительных ситуаций . . . }
Создание иерархии исключений При использовании такого подхода для каждого вида исключительных ситуаций создается свой класс, наследующий от класса Exception. Эти классы могут содержать свои данные и методы для корректной передачи информации и обработки соответствующей исключительной ситуации.
// класс-исключение о нарушении размеров матриц при их перемножении class Dimension. Product. Exception : Exception { Matrix ob 1, ob 2; // ссылки на объекты-матрицы // конструктор класса-исключения public Dimension. Product. Exception(Matrix a, Matrix b) ob 1 = a; ob 2 = b; { } // метод обработки исключения – печати подробного сообщения об ошибке public void Exception. Handler() { Console. Write. Line("Сделана попытка перемножения матриц: "); ob 1. Output. Matrix(); Console. Write. Line(); ob 2. Output. Matrix(); Console. Write. Line("Такие матрицы перемножить нельзя из-за неправильных размеров"); } }
// класс-исключение о некорректный размерах матрицы class Bad. Dimension. Exception : Exception { // размеры, которые использовались при неудачном создании матрицы int rows, cols; // конструктор класса-исключения public Bad. Dimension. Exception(int m, int n) {rows = m; cols = n; } // метод обработки исключения – печати подробного сообщения об ошибке public void Exception. Handler() { Console. Write. Line("Попытка создания матрицы с некорректными размерами"); if (rows<=0) Console. Write. Line("Количество строк матрицы не может быть равным {0}", rows); if (cols <= 0) Console. Write. Line("Количество столбцов матрицы не может быть равным {0}", cols); }}
try { // в этом фрагменте кода может возникнуть исключение некорректных //размеров при создании матрицы и при перемножении двух матриц Matrix x, y, z; x = new Matrix(2, 5); y = new Matrix(3, 4); x. Input. Matrix(); y. Input. Matrix(); z = x * y; z. Output. Matrix(); } catch (Dimension. Product. Exception ex) { // вызов обработчика исключения, связанного с умножением матриц ex. Exception. Handler(); } catch (Bad. Dimension. Exception ex) { // вызов обработчика исключения, связанного ex. Exception. Handler(); } созданием матрицы некорректного размера
Согласно принципу полиморфизма можно создавать один обработчик catch для нескольких видов исключений. Если имеется иерархия классов-исключений, достаточно создавать обработчик catch только для исключения базового типа. Универсальная обработка исключений-наследников производится с помощью переопределения виртуальных функций базового класса. Например, создадим абстрактный базовый класс иерархии – класс Matrix. Exception. В нем объявим абстрактный метод Exception. Handler(), который предназначен для обработки ошибки. Все классы-исключения теперь должны наследовать от класса Matrix. Exception и переопределять абстрактный метод Exception. Handler() этого класса. Классы-наследники могут содержать и другие методы, которые позволяют, если не устранить ошибку, то хотя бы предотвратить ее влияние на последующий ход выполнения программы (корректное освобождение ресурсов, занимаемых объектом, присвоение переменным объекта корректных значений и пр. ). Вызвать эти методы можно из метода Exception. Handler() конкретного класса.
Пример // абстрактный базовый класс иерархии исключений с // единственным абстрактным методом обработки исключения abstract class Matrix. Exception : Exception { abstract public void Exception. Handler(); }
// класс-исключение о нарушении размеров матриц при их перемножении class Dimension. Product. Exception : Matrix. Exception { Matrix ob 1, ob 2; // конструктор класса-исключения public Dimension. Product. Exception(Matrix a, Matrix b) { ob 1 = a; ob 2 = b; } // переопределенный абстрактный метод обработки исключения public override void Exception. Handler() { Console. Write. Line("Сделана попытка перемножения матриц: "); ob 1. Output. Matrix(); Console. Write. Line(); ob 2. Output. Matrix(); Console. Write. Line("Такие матрицы перемножить нельзя из-за неправильных размеров"); }}
try { // в этом фрагменте кода может возникнуть исключение // некорректных размеров при создании матрицы и при // перемножении двух матриц Matrix x, y, z; x = new Matrix(2, 3); y = new Matrix(3, 4); x. Input. Matrix(); y. Input. Matrix(); z = x * y; z. Output. Matrix(); } catch (Matrix. Exception ex) { // общий обработчик Matrix. Exception исключений-наследников // вызов метода обработки исключения того класса, // которому принадлежит объект ex класса
Обработка исключений.pptx