Читаем Интернет-журнал "Домашняя лаборатория", 2007 №9 полностью

Язык C# позволяет создать проверяемый блок, в котором будет осуществляться проверка результата вычисления арифметических выражений. Если результат вычисления значения источника выходит за диапазон возможных значений целевой переменной, то возникнет исключение (говорят также: "будет выброшено исключение") соответствующего типа. Если предусмотрена обработка исключения, то дальнейшее зависит от обработчика исключения. В лучшем случае, программа сможет продолжить корректное выполнение. В худшем, — она остановится и выдаст информацию об ошибке. Заметьте, не произойдет самого опасного — продолжения работы программы с неверными данными.

Синтаксически проверяемый блок предваряется ключевым словом checked, в теле такого блока арифметические преобразования проверяются на допустимость. Естественно, подобная проверка требует дополнительных временных затрат. Если группа операторов в теле такого блока нам кажется безопасной, то их можно выделить в непроверяемый блок, используя ключевое слово unchecked.

Замечу еще, что и в непроверяемом блоке при работе методов Convert все опасные преобразования проверяются и приводят к выбрасыванию исключений. Приведу пример, демонстрирующий все описанные ситуации:

///

/// Демонстрация проверяемых и непроверяемых преобразований.

/// Опасные проверяемые преобразования приводят к исключениям.

/// Опасные непроверяемые преобразования приводят к неверным

/// результатам, что совсем плохо.

/// 

public void CheckUncheckTest()

     x = —25 ^2;

     WhoIsWho ("x", x);

     b= 2 55;

     WhoIsWho("b",b);

     // Проверяемые опасные преобразования.

     // Возникают исключения, перехватываемые catch-блоком,

     checked

     {

         try

         {

             b += 1;

         }

         catch (Exception e)

         {

              Console.WriteLine("Переполнение при вычислении b");

              Console.WriteLine(e);

         }

         try

         {

               b = (byte)x;

          }

          catch (Exception e)

          {

               Console.WriteLine("Переполнение при преобразовании к byte");

               Console.WriteLine(e);

          }

         // непроверяемые опасные преобразования

         unchecked

          {

               try

               {

                   b +=1;

                          WhoIsWho ("b", b);

                   b = (byte)x;

                   WhoIsWho ("b", b);

                   ux= (uint)x;

                   WhoIsWho ("ux", ux);

                   Console.WriteLine("Исключений нет, но результаты не верны!");

               }

               catch (Exception е)

               {

                   Console.WriteLine("Этот текст не должен появляться");

                   Console.WriteLine (е);

                }

               // автоматическая проверка преобразований в Convert

               // исключения возникают, несмотря на unchecked

               try

               }

                    b = Convert.ToByte(х);

               }

               catch (Exception е)

               {

                     Console.WriteLine("Переполнение при преобразовании к byte!");

                     Console.WriteLine(е);

                }

                try

                {

                     ux= Convert.ToUInt32(х);

                }

                catch (Exception e)

                {

                     Console.WriteLine("Потеря знака при преобразовании к uint!");

                      Console.WriteLine (e);

                 }

            }

      }

}

Исключения и охраняемые блоки. Первое знакомство

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

Заметьте, рекомендуемый стиль программирования в C# отличается от стиля, принятого в языках С/C++, где функция, в которой возникла ошибка, завершается нормальным образом, уведомляя об ошибке в возвращаемом значении результата. Вызывающая программа должна анализировать результат, чтобы понять, была ли ошибка в работе вызванной функции и какова ее природа. При программировании в стиле C# ответственность за обнаружение ошибок лежит на вызванной программе. Она должна не только обнаружить ошибку, но и явно сообщить о ней, выбрасывая исключение соответствующего типа. Вызываемая программа должна попытаться исправить последствия ошибки в обработчике исключения. Подробности смотри в лекции про исключения.

В состав библиотеки FCL входит класс Exception, свойства и методы которого позволяют работать с исключениями как с объектами, получать нужную информацию, дополнять объект собственной информацией. У класса Exception — большое число потомков, каждый из которых описывает определенный тип исключения. При проектировании собственных классов можно параллельно проектировать и классы, задающие собственный тип исключений, который может выбрасываться в случае ошибок при работе методов класса. Создаваемый класс исключений должен быть потомком класса Exception.

Перейти на страницу:

Похожие книги