Скачать презентацию Исключения Лекция 27 11 2012 г 1 Скачать презентацию Исключения Лекция 27 11 2012 г 1

Лекция-11_Пр-е.ppt

  • Количество слайдов: 21

Исключения Лекция 27. 11. 2012 г. 1 Исключения Лекция 27. 11. 2012 г. 1

Понятие исключения Исключение — это событие, которое не ожидается в «штатном» режиме работы программы, Понятие исключения Исключение — это событие, которое не ожидается в «штатном» режиме работы программы, и своим появлением препятствует дальнейшему ее выполнению, например: • попытка деления на нуль, • обращение к несуществующей базе данных, • открытие поврежденного файла, • обрыв связи при передаче данных по сети и пр. Говорят, что при наступлении подобных событий возбуждается исключение. Инициатором возбуждения исключения может быть исполнительная система (CLR) или код приложения. В дальнейшем исключение должно быть обработано с целью корректного выхода из сложившейся ситуации. Язык С# имеет развитые средства для обработки исключений. Лекция 27. 11. 2012 г. 2

Обработка завершения (termination handling) С понятием обработка исключений тесно связано понятие обработка завершения. Обработка Обработка завершения (termination handling) С понятием обработка исключений тесно связано понятие обработка завершения. Обработка завершения реализуется в программе двумя последовательно расположенными блоками: try {…} и finally {…}. В блок try помещается код, способный с определенной вероятностью возбудить исключение и требующий общей очистки ресурсов или восстановления после исключения. Блок finally содержит код, исполнение которого гарантируется при любых условиях. После исчерпания инструкций в блоке finally начинают выполняться инструкции, расположенные сразу за этим блоком. Лекция 27. 11. 2012 г. 3

Обработка завершения Обработчик завершения (блок finally) гарантирует, что его код будет выполнен независимо от Обработка завершения Обработчик завершения (блок finally) гарантирует, что его код будет выполнен независимо от того, как происходит выход из защищенного участка программы (блока try), даже если это выход с помощью goto или return. using System; public class A { public static void Main() { int k = Fun(); Console. Read. Key(); } static int Fun() { try { Console. Write. Line("TRY"); return 0; } finally { Console. Write. Line("FINALLY"); } } } Лекция 27. 11. 2012 г. 4

Обработка завершения using System; public class A { public static void Main() { int Обработка завершения using System; public class A { public static void Main() { int k = Fun(); Console. Read. Key(); } static int Fun() { try { Console. Write. Line("TRY"); goto m; } finally { Console. Write. Line("FINALLY"); } m: Console. Write. Line("RETURN"); return 0; } } Лекция 27. 11. 2012 г. 5

Обработка завершения using System; class Exception. Test. Class { public static void Main(){ int Обработка завершения using System; class Exception. Test. Class { public static void Main(){ int x = 0; try { int y = 100 / x; } catch (Arithmetic. Exception e) { Console. Write. Line("Arithmetic. Exception Handler: {0}", e. Message); } catch (Exception e) { Console. Write. Line("Generic. Exception Handler: {0}", e. Message); } finally { Console. Write. Line("FINALLY"); Console. Read. Key(); } } } Лекция 27. 11. 2012 г. 6

Обработка исключения (exception handling) Для обработки исключения в код программы включаются один или несколько Обработка исключения (exception handling) Для обработки исключения в код программы включаются один или несколько обработчиков исключений (блоков catch), каждый из которых настроен на свой тип исключения, который указывается в скобках после catch (его еще называют фильтром исключения). В программах на C# в качестве типа исключения можно использовать только тип System. Exception или производный от него. CLR просматривает блоки catch сверху вниз, поэтому «узкоспециализированные» исключения нужно размещать выше. Вначале должны следовать наиболее удаленные потомки, потом — их базовые классы и лишь в конце — System. Exception (или блок catch без указания типа исключения). В противном случае компилятор С# генерирует ошибку, так как более специализированный блок catch, размещенный после менее специализированного, будет недостижим. Лекция 27. 11. 2012 г. 7

Обработка исключения public class A { public static void Main() { int k = Обработка исключения public class A { public static void Main() { int k = -1; try { k = Fun(0); } catch (Arithmetic. Exception e) { Console. Write. Line("Arithmetic. Exception Handler: {0}", e. Message); !! } catch (Exception e) { Console. Write. Line("Generic Exception Handler: {0}", e. Message); } Console. Write. Line("k = {0}", k); } static int Fun(int x) { int y = 999; try { 1/0 y = 1 / x; Console. Write. Line("TRY"); } catch (Argument. Exception e) { ? ? Console. Write. Line("Argument. Exception Handler: {0}", e. Message); } return y; } } Лекция 27. 11. 2012 г. 8

Алгоритм обработки исключения Старт Выполнить очередную инструкцию Есть исключ-е? нет да Найти ближайший объемлющий Алгоритм обработки исключения Старт Выполнить очередную инструкцию Есть исключ-е? нет да Найти ближайший объемлющий блок try (Т 2) нет Есть успешный catch? Найти предыдущий блок try да Выполнить глобальную раскрутку Запомнить блок try с «успешным» блоком catch (Т 1) Лекция 27. 11. 2012 г. 9

Алгоритм глобальной раскрутки Начать глобальную раскрутку Выполнить блок catch Продолжить да Перейти к самому Алгоритм глобальной раскрутки Начать глобальную раскрутку Выполнить блок catch Продолжить да Перейти к самому «нижнему» блоку try (Т 2) Это Т 1? нет Есть finally? нет Найти предыдущий блок try да Выполнить блок finally Лекция 27. 11. 2012 г. 10

Глобальная раскрутка (начало) using System; public class A { public static void Main() { Глобальная раскрутка (начало) using System; public class A { public static void Main() { int k = -1; try { k = Fun 1(0); T 1 } catch (Arithmetic. Exception e) { // 3 Console. Write. Line("Arithmetic. Exception Handler: {0}", e. Message); } catch (Exception e) { Console. Write. Line("Generic Exception Handler: {0}", e. Message); } finally { Console. Write. Line("Main: FINALLY"); // 4 } Console. Write. Line("k = {0}", k); // 5 Console. Read. Key(); } static int Fun 1(int x) {. . . } static int Fun(int x) {. . . } } Лекция 27. 11. 2012 г. 11

Глобальная раскрутка (продолжение) public class A {. . . static int Fun 1(int x) Глобальная раскрутка (продолжение) public class A {. . . static int Fun 1(int x) { try { int n = Fun(x); ? ? } catch (Argument. Exception e) { Console. Write. Line("Argument. Exception Handler: {0}", e. Message); } finally { Console. Write. Line("Fun 1: FINALLY"); // 2 } return 1000; } static int Fun(int x) { int y = 999; try { y = 1 / x; Console. Write. Line("Fun: TRY"); T 2 } catch (Argument. Exception e) { Console. Write. Line("Argument. Exception Handler: {0}", e. Message); } finally { Console. Write. Line("Fun: FINALLY"); // 1 } return y; } } Лекция 27. 11. 2012 г. 12

Открытые свойства класса System. Exception Data – возвращает коллекцию пар ключ/значение, которая дает дополнительную Открытые свойства класса System. Exception Data – возвращает коллекцию пар ключ/значение, которая дает дополнительную определенную пользователем информацию об исключении (по умолчанию пусто) Help. Link – возвращает URL-адрес файла помощи, в котором подробно описывается ошибка Inner. Exception – информация о предыдущих исключениях, которые привели к возникновению данного Message – текстовое описание данной ошибки, которое устанавливается через параметр конструктора Source – имя сборки, вызвавшей исключение Stack. Trace – последовательность вызовов, приведших к генерации исключения Target. Site – возвращает объект типа Method. Base, описывающий различные детали метода, вызвавшего исключение (имя метода вернет метод To. String()). Лекция 27. 11. 2012 г. 13

Конструкторы класса System. Exception Базовый тип Exception определяет четыре стандартных конструктора: Ø открытый конструктор Конструкторы класса System. Exception Базовый тип Exception определяет четыре стандартных конструктора: Ø открытый конструктор без параметров (конструктор по умолчанию), создающий экземпляр типа и устанавливающий для всех его полей и свойств значения по умолчанию; Ø открытый конструктор, принимающий один параметр String и создающий экземпляр типа с заданным текстом сообщения; Ø конструктор, принимающий два параметра: строку (String) и экземпляр типа, производного от Exception, и создающий экземпляр с заданными текстом сообщения и внутренним исключением; Ø закрытый конструктор, принимающий объекты Serializationlnfo и Streaming. Context, которые десериализуют экземпляры объекта, производного от Exception. Определяя собственный тип исключений, следует реализовать в нем эти четыре конструктора и вызывать соответствующий конструктор из базового типа. Лекция 27. 11. 2012 г. 14

Иерархия классов исключений В FCL в разных пространствах имен определено множество классов исключений, производных Иерархия классов исключений В FCL в разных пространствах имен определено множество классов исключений, производных от System. Exception. Основными прямыми потомками System. Exception являются: - System. Exception - базовый класс для исключений CLR, - System. Application. Exception - базовый класс для исключений приложений. Благодаря этому можно создавать блок catch, перехватывающий все CLR-исключения или все исключения приложения. Однако, это правило соблюдается не полностью: некоторые типы исключений являются прямыми потомками Exception (например, Isolated. Storage. Exception), другие CLR-исключения наследуют Application. Exception (в частности, Targetlnvocation. Exception), а третьи исключения приложений являются производными от System. Exception (к примеру, Format. Exception). Лекция 27. 11. 2012 г. 15

Генерация исключений При создании собственных методов можно генерировать исключения, если метод не в состоянии Генерация исключений При создании собственных методов можно генерировать исключения, если метод не в состоянии выполнить возложенную на него задачу. При этом нужно ответить на два важных вопроса: 1) Какой производный от Exception тип исключения будет генерироваться? - Рекомендуется выбирать содержательное имя типа из числа имеющихся в FCL, либо определять собственный тип, наследующий от одного из имеющихся. При создании иерархий типов исключений, рекомендуется создавать максимально плоскую и широкую иерархию, чтобы свести до минимума число базовых классов. Причина: базовые классы обеспечивают обработку многих ошибок как одной ошибки, и это обычно опасно. Таким образом, никогда не следует генерировать тип System. Exception и надо соблюдать максимальную осторожность при генерации любого другого типа исключений, являющегося базовым классом. Лекция 27. 11. 2012 г. 16

Генерация исключений 2) Какое строковое сообщение передавать в конструктор типа исключения? - При генерации Генерация исключений 2) Какое строковое сообщение передавать в конструктор типа исключения? - При генерации исключения нужно предоставлять строковое сообщение с детальной информацией о том, почему метод не смог выполнить свою задачу. Если исключение перехватывается и обрабатывается, это строковое сообщение не видно, а сообщения необработанных исключений обычно регистрируются в журнале. Необработанное исключение информирует разработчика программы об обнаруженном дефекте приложения, и позволяет ему в дальнейшем усовершенствовать программу с целью устранения дефекта. Конечный пользователь не должен видеть это строковое сообщение, это – информация для разработчика приложения. Лекция 27. 11. 2012 г. 17

Генерация исключений При создании собственных классов исключений необходимо учитывать следующие рекомендации: 1) Проверяйте аргументы Генерация исключений При создании собственных классов исключений необходимо учитывать следующие рекомендации: 1) Проверяйте аргументы своих методов. 2) Блоков finally не должно быть слишком много. 3) Не всякое исключение следует перехватывать. 4) Корректное восстановление после исключения. 5) Отмена незавершенных операций при невосстановимых исключениях. 6) Сокрытие деталей реализации для сохранения контракта. Лекция 27. 11. 2012 г. 18

Генерация исключений using System; namespace NDP_UE_CS { class Log. Table. Overflow. Exception : Exception Генерация исключений using System; namespace NDP_UE_CS { class Log. Table. Overflow. Exception : Exception { const string overflow. Message = "The log table has overflowed. "; public Log. Table. Overflow. Exception(string aux. Message, Exception inner): base(String. Format("{0} - {1}", overflow. Message, aux. Message), inner) { this. Help. Link = "http: //msdn. microsoft. com"; this. Source = "Exception_Class_Samples"; } } class Log. Table { public Log. Table(int num. Elements) { log. Area = new string[num. Elements]; elem. In. Use = 0; } protected string[] log. Area; protected int elem. In. Use; public int Add. Record(string new. Record) { log. Area[5]=“Log record number 5” ? ? ? try { log. Area[elem. In. Use] = new. Record; return elem. In. Use++; } catch (Exception e) { 1 throw new Log. Table. Overflow. Exception(String. Format ("Record "{0}" was not logged. ", new. Record), e); } } } Лекция 27. 11. 2012 г. 19

Генерация исключений class Overflow. Demo { public static void Main() { Log. Table log Генерация исключений class Overflow. Demo { public static void Main() { Log. Table log = new Log. Table(4); Console. Write. Line( "This example of n Exception. Message, n" + " Exception. Help. Link, n Exception. Source, n" + " Exception. Stack. Trace, and n Exception. " + "Target. Site ngenerates the following output. "); try { for (int count = 1; ; count++) log. Add. Record(String. Format("Log record number {0}", count)); } 2 catch (Exception ex) { Console. Write. Line("n. Message ---n{0}", ex. Message); Console. Write. Line("n. Help. Link ---n{0}", ex. Help. Link); Console. Write. Line("n. Source ---n{0}", ex. Source); Console. Write. Line("n. Stack. Trace ---n{0}", ex. Stack. Trace); Console. Write. Line("n. Target. Site ---n{0}", ex. Target. Site); Console. Write. Line("n. Inner. Exception ---n{0}", ex. Inner. Exception); } Console. Read. Key(); } } } Лекция 27. 11. 2012 г. 20

Исключения и обработка исключений в C# Лекция 27. 11. 2012 г. 21 Исключения и обработка исключений в C# Лекция 27. 11. 2012 г. 21