Страница 188 из 502
Обработка исключительных ситуаций - “изящный” способ устранения программных ошибок
Одно из главных преимуществ обработки исключительных ситуаций заключается в том, что она позволяет вовремя отреагировать на ошибку в программе и затем продолжить ее выполнение. В качестве примера рассмотрим еще одну программу, в которой элементы одного массива делятся на элементы другого. Если при этом происходит деление на нуль, то генерируется исключение DivideByZeroException. Обработка подобной исключительной ситуации заключается в том, что программа уведомляет об ошибке и затем продолжает свое выполнение. Таким образом, попытка деления на нуль не приведет к аварийному завершению программы из-за ошибки при ее выполнении. Вместо этого ошибка обрабатывается "изящно", не прерывая выполнение программы.
<b>// Изящно обработать исключительную ситуацию и продолжить выполнение программы.</b>
<b>using System;</b>
<b>class ExcDemo3 {</b>
<b> static void Main() {</b>
<b> int[] numer = { 4, 8, 16, 32, 64, 128 };</b>
<b> int[] denom = { 2, 0, 4, 4, 0, 8 };</b>
<b> for(int i=0; i < numer.Length; i++) {</b>
<b> try {</b>
<b> Console.WriteLine(numer[i] + " / <sup>"</sup> +</b>
<b> denom[i] + <sup>"</sup> равно <sup>"</sup> +</b>
<b> numer[i]/denom[i]);</b>
<b> }</b>
<b> catch (DivideByZeroException) {</b>
<b> // Перехватить исключение.</b>
<b> Console.WriteLine("Делить на нуль нельзя!");</b>
<b> }</b>
<b> }</b>
<b> }</b>
<b>}</b>
Ниже приведен результат выполнения этой программы.
<b>4/2 равно 2</b>
<b>Делить на нуль нельзя!</b>
<b>16/4 равно 4 </b>
<b>32/4 равно 8 </b>
<b>Делить на нуль-нельзя!</b>
<b>128 / 8 равно 16</b>
Из данного примера следует еще один важный вывод: как только исключение обработано, оно удаляется из системы. Поэтому в приведенной выше программе проверка ошибок в блоке try начинается снова на каждом шаге цикла for, при условии, что все предыдущие исключительные ситуации были обработаны. Это позволяет обрабатывать в программе повторяющиеся ошибки.
Применение нескольких операторов catch
С одним оператором try можно связать несколько операторов catch. И на практике это делается довольно часто. Но все операторы catch должны перехватывать исключения разного типа. В качестве примера ниже приведена программа, в которой перехватываются ошибки выхода за границы массива и деления на нуль.
<b>// Использовать несколько операторов catch.</b>
<b>using System;</b>
<b>class ExcDemo4 {</b>
<b> static void Main() {</b>
<b> // Здесь массив numer длиннее массива denom.</b>
<b> int[] numer = { 4, 8, 16, 32, 64, 128, 256, 512 };</b>
<b> int[] denom = { 2, 0, 4, 4, 0, 8 };</b>
<b> for(int i=0; i < numer.Length; i++) {</b>
<b> try {</b>
<b> Console.WriteLine(numer[i] + " / " +</b>
<b> denom[i] + " равно " + numer[i]/denom[i ]) ;</b>
<b> }</b>
<b> catch (DivideByZeroException) {</b>
<b> Console.WriteLine("Делить на нуль нельзя!");</b>
<b> }</b>
<b> catch (IndexOutOfRangeException) {</b>
<b> Console.WriteLine("Подходящий элемент не найден.");</b>
<b> }</b>
<b> }</b>
<b> }</b>
<b>}</b>
Вот к какому результату приводит выполнение этой программы.
<b>4/2 равно 2</b>
<b>Делить на нуль нельзя!</b>
<b>16/4 равно 4 </b>
<b>32/4 равно 8 </b>
<b>Делить на нуль нельзя!</b>
<b>128 / 8 равно 16 </b>
<b>Подходящий элемент не найден.</b>
<b>Подходящий элемент не найден.</b>
Как следует из приведенного выше результата, каждый оператор catch реагирует только на свой тип исключения.
Вообще говоря, операторы catch выполняются по порядку их следования в программе. Но при этом выполняется только один блок catch, в котором тип исключения совпадает с типом генерируемого исключения. А все остальные блоки catch пропускаются.
Перехват всех исключений
Время от времени возникает потребность в перехвате всех исключений независимо от их типа. Для этой цели служит оператор catch, в котором тип и переменная исключения не указываются. Ниже приведена общая форма такого оператора.