Лекция 9. 14. Исключительные ситуации

14. Исключительные ситуации

Нарушение в работе программы (не корректное действие) называется исключением. Исключение останавливает текущий поток программы и если никакие меры не предпринимаются, программа просто прекращает выполнение.

Причиной исключений могут быть ошибки в программе (например, деление числа на ноль) или неожиданный ввод (например, выбор несуществующего файла, или вместо цифры для выполнения арифметических действий – буква).

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

Обработку исключений может выполнять

системный обработчик исключений или

– написанный пользователем программный код, который выводит сообщение.

Для обработки исключений используются глобальные и локальные обработчики исключений.

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

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

Обработка локальных исключений в C# реализована с помощью ключевых слов, — try, catch и finally — с помощью которых программа обнаруживает исключения, устраняет их и продолжает выполнение. Они способствуют повышению надежности приложений.

14.1. Виды исключений:

Исключения имеют типы, являющиеся производными от System.Exception. Некоторые исключения, генерируемые при компиляции:

Тип_Исключения Описание
ArithmeticException Основной класс исключений, происходящих при выполнении арифметических операций, таких как DivideByZeroException и OverflowException.
ArrayTypeMismatchException Создается, когда тип сохраняемого значения несовместим с фактическим типом массива.
DivideByZeroException Создается при попытке разделить целое число на ноль.
IndexOutOfRangeException Создается при попытке индексирования массива, если индекс меньше нуля или выходит за границы массива.
InvalidCastException Создается, когда неверно выполнено динамическое приведение типов.
NullReferenceException Создается при попытке ссылки на объект, значение которого равно null.
OutOfMemoryException Создается при неудаче попытки выделения памяти с помощью оператора new. Это означает, что память, доступная для среды выполнения, уже исчерпана.
OverflowException Создается при переполнении арифметической операции.
StackOverflowException Создается, когда стековая память переполнена.

14.2.Существуют два типа блоков:

I. Try Catch // попробовать исключить

II. Try Catch … Finally // попробовать исключить в финал

I. Try, Catch

Ключевые слова try и catch используются вместе как составной оператор. Для таких блоков характерна вложенность. Если предполагается, что блок кода может вызвать исключение, используют ключевое слово try и catch (параметр), чтобы сохранить код, который будет выполнен при возникновении исключения.

Блок, которому предшествует ключевое слово try, называется охраняемым (контролируемым) блоком или try-блоком. Блок, которому предшествует конструкция catch (параметр), называется блоком перехватчиком исключения или catch-блоком.

При отсутствии блоков try и catch произойдет сбой программы.

Синтаксис инструкции:

try

{

// Блок кода, подлежащий проверки на наличие ошибок

}

catch (<Тип_Исключения1>)

{

// Код обработчика исключения (<Тип_Исключения1>)

}

catch (<Тип_Исключения2>)

{

// Код обработчика исключения (<Тип_Исключения2>)

}…..

С try -блоком может быть связана не одна, а несколько catch -инструкций. Какая из них будет выполнена, определит тип исключения. Будет выполнена та catch -инструкция, тип исключения которой совпадает с типом сгенерированного исключения (а все остальные будут проигнорированы).

Если исключение не сгенерируется, то try -блок завершается нормально, и все его catch -инструкции игнорируются. Выполнение программы продолжается с первой инструкции, которая стоит после последней инструкции catch. Таким образом, catch -инструкция выполняется только в случае, если сгенерировано соответствующее исключение.

Пример1, в котором в результате деления на ноль создается исключение, которое затем перехватывается. В программе генерируется исключение типа DivideByZeroException – деление на 0

int x = 0, y = 0; // знаменатель равен 0

try

{

x = 10 / y; // Проверяемая инструкция, возможно деление на 0

Console.WriteLine("Ответ x= "+x);

}

catch (DivideByZeroException) // Обработчик исключения

{

Console.WriteLine("Попытка деления на 0.");

}

 
 


Блоки try включают операторы программы, которые могут вызвать исключительную ситуацию, например y=0.

Теперь заменим y=0 на y=2:

{

int x = 0, y = 2; // знаменатель равен, например 2 (отличен от 0)

try

{

x = 10 / y; // Проверяемая инструкция, возможно деление на 0

Console.WriteLine("Ответ x= "+x);

}

catch (DivideByZeroException) // Обработчик исключения

{

Console.WriteLine("Попытка деления на 0.");

}

}

 
 


Пример2, в котором происходит индексация массива и попытка индексировать массив за пределами его границ, вызывает ошибку нарушения диапазона.

static void Main(string[] args)

{

int[] N = new int[4]; // массив для 4-х элементов

try

{

Console.WriteLine("Перед генерированием исключения.");

// связанное с попаданием индекса вне диапазона

for (int i = 0; i < 10; i++) //в цикле индексируется массив от 0 до 9

{

N[i] = i;

Console.WriteLine("N[{0}]:{1}", i, N[i]);

}

Console.WriteLine("Этот текст не отображается");

}

catch (IndexOutOfRangeException)

{

//Перехватываем исключение.

Console.WriteLine("Индекс вне диапазона");

}

Console.WriteLine("После catch-инструкции");

Console.ReadLine();

}

 
 


В программе намеренно генерируется исключение типа IndexOutOfRangeException, а затем это исключение перехватывается.

В программе объявляется массив для 4-х элементов, а в цикле делается попытка индексировать этот массива от 0 до 9. Как только значение индекса устанавливается равным четырем, генерируется исключение типа IndexOutOfRangeException.

Ключевые аспекты обработки исключений:

1. проверяемый код содержится внутри try-блока,

2. при возникновении исключения выполнение try-блока прекращается, а само исключение перехватывается catch инструкцией,

3. catch инструкция не вызывается, а ей передается управление программой.

4. после выполнения catch инструкции программа продолжится со следующей инструкции.

Если try-блоком исключение не сгенерировано, ни одна из catch инструкций не выполняется и управление программой будет передано инструкции, следующей за catch инструкций.

Если заменить в цикле for (int i = 0; i < 10; i++) верхний индекс на

for (int i = 0; i < N.Length; i++), то границы индексирования массива не нарушаются. Поэтому исключение не генерируется и catch-блок не выполняется.

 
 


Если не создать локального обработчика исключения, то C# система динамического управления перехватит исключение, сообщит об ошибке и завершит программу.

С try-блоком можно связать несколько catch инструкций. Все catch инструкции должны перехватывать исключения различного типа.

Пример3. Программа перехватывает как ошибку нарушения границ массива, так и ошибку деления на нуль.

static void Main(string[] args)

{

int[] N = {4,8,16,32,64,128,256,512}; // массив из 8 элементов

int[] D = {2, 0, 4, 4, 0, 8}; // массив из 6 элементов

for (int i = 0; i < N.Length; i++) //в цикле по всем элементам

try

{

Console.WriteLine(N[i] + " / "+ D[i] + " = " + N[i]/D[i]);

}

catch (DivideByZeroException)

{

//Перехватываем исключение.

Console.WriteLine("На нуль делить нельзя!");

}

catch (IndexOutOfRangeException)

{

//Перехватываем исключение.

Console.WriteLine("Нет соответствующего элемента.");

}

Console.ReadLine();

}

Каждая catch инструкция реагирует только на собственный тип исключения.

II. Try, Catch, Finally

Иногда возникает потребность определить программный блок, который должен выполняться по выходу из try/catch блока. Исключение может вызвать ошибку, которая является причиной преждевременного возврата из текущего метода. Удобный путь выхода из этого – блок finally.

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

Синтаксис инструкции:

class ProgramTryCatchFinally

{

static void Main()

{

try

{

// Блок кода, предназначенный для обработки ошибок

}

catch (<Тип_Исключения1>)

{

// Обработчик для исключения (<Тип_Исключения1>).

}

catch (<Тип_Исключения2>)

{

// Обработчик для исключения (<Тип_Исключения2>).

}

…..

finally

{

// Код завершения обработки исключений.

}

Не зависимо от итога выполнения try/catch блоков, блок finally выполняется обязательно.

Задача. Используя закон Ома рассчитать величину тока. Проект оконное приложение. Сначала создается интерфейс будущего приложения, а затем обработчик события щелчка по кнопке «Вычислить».

       
   
 


Листинг программы

private void button1_Click(object sender, EventArgs e)

{

try

{

int U = int.Parse(textBox1.Text); // преобразование строкового

int R = int.Parse(textBox2.Text); // отображения в целое

double I = (double)U / R;

label3.Text = I.ToString()+ " A"; // преобразование числа в строку

}

catch

{

label3.Text = "Нельзя вводить буквы, символы и 0";

}

Форматы ввода/вывода под Оконное приложение

int а = int.Parse(textBox1.Text); //преобразование текста, введенного

// в textBox1 в целое число

double b = double.Parse(textBox1.Text); //преобразование текста, введенного

// в textBox1 в вещественное число

label3.Text = S.ToString()+ " руб."; // преобразование числа S в строку

label1.Text =String.Format(“{0:f 3}”,x); // преобразование числа x в строку c форматным выводом символов в компонент label1 через его свойство Text,

где 0 – индекс переменной, f – мантисса, 3 – количество символов после зпт.

label1.Text =String.Format(“{0,5:f 2}”,x); // преобразование числа x в строку c форматным выводом символов в компонент label1 через его свойство Text,

где 0 – индекс переменной, 5 – количество выводимых символов, f – мантисса, 2 – количество символов после зпт.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: