Лекция 19. Обработка исключений

Иногда при выполнении программы возникают ошибки, которые трудно предусмотреть или предвидеть, а иногда и вовсе невозможно. Например, при передачи файла по сети может неожиданно оборваться сетевое подключение. такие ситуации называются исключениями. Язык C# предоставляет разработчикам возможности для обработки таких ситуаций. Для этого в C# предназначена конструкция try...catch...finally. При возникновении исключения среда CLR ищет блок catch, который может обработать данное исключение. Если такого блока не найдено, то пользователю отображается сообщение о необработанном исключении, а дальнейшее выполнение программы останавливается. И чтобы подобной остановки не произошло, и надо использовать блок try..catch. Например:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 static void Main(string[] args) { int[] a = new int[4]; try { a[5] = 4; // тут возникнет исключение, так как у нас в массиве только 4 элемента Console.WriteLine("Завершение блока try"); } catch (Exception ex) { Console.WriteLine("Ошибка: " + ex.Message); } finally { Console.WriteLine("Блок finally"); } Console.ReadLine(); }

При использовании блока try...catch..finally вначале выполняются все инструкции между операторами try и catch. Если между этими операторами вдруг возникает исключение, то обычный порядок выполнения останавливается и переходит к инструкции сatch. В данном случае у нас явно возникнет исключение в блоке try, так как мы пытаемся присвоить значение шестому элементу массива в то время, как в массиве всего 4 элемента. И дойдя до строки a[5] = 4;, выполнение программы остановится и перейдет к блоку catch

Инструкция catch имеет следующий синтаксис: catch (тип_исключения имя_переменной). В нашем случае объявляется переменная ex, которая имеет тип Exception. Но если возникшее исключение не является исключением типа, указанного в инструкции сatch, то оно не обрабатывается, а программа просто зависает или выбрасывает сообщение об ошибке.

Однако так как тип Exception является базовым классом для всех исключений, то выражение catch (Exception ex) будет обрабатывать практически все исключения. Вся обработка исключения в нашем случае сводится к выводу на консоль сообщении об исключении, которое в свойстве message класса Exception.

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

Обработка нескольких исключений

При необходимости мы можем разграничить обработку различных типов исключений, включив дополнительные блоки catch:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 static void Main(string[] args) { try {   } catch (FileNotFoundException e) { // Обработка исключения, возникшего при отсутствии файла } catch (IOException e) { // Обработка исключений ввода-вывода } Console.ReadLine(); }

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

При этом более частные исключения следует помещать в начале, и только потом более общие классы исключений. Например, сначала обрабатывается исключение IOException, и только потом Exception (так как IOException наследуется от класса Exception).

Оператор throw

Чтобы сообщить о выполнении исключительных ситуаций в программе, можно использовать оператор throw. То есть с помощью этого оператора мы сами можем создать исключение и вызвать его в процессе выполнения. Например, в нашей программе происходит ввод строки, и мы хотим, чтобы, если длина строки будет больше 6 символов, возникало исключение:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 static void Main(string[] args) { try { string message = Console.ReadLine(); if (message.Length > 6) { throw new Exception("Длина строки больше 6 символов"); } } catch (Exception e) { Console.WriteLine("Ошибка: " + e.Message); } Console.ReadLine(); }

Обработка исключений и условные конструкции

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

1 2 3 4 5 6 7 8 9 static void Main(string[] args) { Console.WriteLine("Введите число"); int x = Int32.Parse(Console.ReadLine());   x *= x; Console.WriteLine("Квадрат числа: " + x); Console.Read(); }

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

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 static void Main(string[] args) { Console.WriteLine("Введите число"); int x; string input = Console.ReadLine(); if (Int32.TryParse(input, out x)) { x *= x; Console.WriteLine("Квадрат числа: " + x); } else { Console.WriteLine("Некорректный ввод"); } Console.Read(); }

Метод Int32.TryParse() возвращает true, если преобразование можно осуществить, и false - если нельзя. При допустимости преобразования переменная x будет содержать введенное число. Так, не используя try...catch можно обработать возможную исключительную ситуацию.

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

Фильтры исключений

В C# 6.0 (Visual Studio 2015) была добавлена такая функциональность, как фильтры исключений. Они позволяют обрабатывать исключения в зависимости от определенных условий:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int x = 1; int y = 0;   try { int result = x / y; } catch(Exception ex) when (y==0) { Console.WriteLine("y не должен быть равен 0"); } catch(Exception ex) { Console.WriteLine(ex.Message); }

В данном случае будет выброшено исключение, так как y=0. Здесь два блока catch, но поскольку для первого блока указано условие с помощью ключевого слова when, то сработает первый блок catch. Если бы y не было бы равно 0, то сработал бы второй блок catch.

 


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



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