Пользовательские классы-исключения в C#
Пользовательские классы-исключения
В предыдущей статье я рассказывал о генерации исключений в программах, написанных на C#. Прочитав её, Вы узнаете для чего предназначен данный механизм и как им пользоваться. А в этой статье я хочу рассказать о том, как создавать свои классы-исключения, т.е. такие классы, объекты которых, можно использовать для генерации исключений оператором throw.
И так, как мы помним, механизм генерации исключений нужен для информирования системы, о том, что в программе произошла некая исключительная ситуация (ошибка) и дальнейшее выполнение программы, без её обработки, невозможно! А объекты-исключения, который как бы «выбрасываются в эфир» оператором throw должны содержать информацию о произошедшей ошибке. И когда Вы разрабатываете свой специфический класс, Вам нужно позаботиться о генерации исключений в нештатных ситуациях, связанных с неправильным использованием этого класса. И вот тут начинается самое интересное…
Как мы помним, объект, который как бы «выбрасывается в эфир» оператором throw должен относиться к классу, который является прямым или косвенным наследником класса «Exception» (из пространства имен «System»), ну или вообще являться объектом этого класса. В примере из предыдущей статьи, мы поступали так:
//Конструктор public Person(string aName, int anAge) { name = aName; //Если указан отрицательный возраст if (anAge < 0) { throw new Exception("Отрицательный возраст"); //Дальше, конструктор выполняться не будет... } age = anAge; }
Строка генерации исключения выделена. Так поступать можно, но не совсем правильно! Почему? Да потому, что при возможности, нужно максимально конкретизировать произошедшую ошибку (чтобы в месте её обработки было легче понять причину возникновения). Это делается как минимум двумя способами:
- генерацией ошибки (объекта) определенного типа (класса), а не обобщенного, такого как «Exception», что использовался в примере выше;
- передачей в создаваемый объект-исключение дополнительной информации.
Как это делается на практике? Ну в нашем примере, причиной ошибки служило некорректное значение аргумента, по-этому вместо объекта класса «Exception» мы могли бы использовать объект стандартного класса «ArgumentException» (думаю, название класса, говорит само за себя) из пространства имен «System«. Выглядеть это могло бы так:
//Конструктор public Person(string aName, int anAge) { name = aName; //Если указан отрицательный возраст if (anAge < 0) { throw new ArgumentException("Отрицательный возраст"); //Дальше, конструктор выполняться не будет... } age = anAge; }
Среди стандартных классов C#, есть ряд классов, которые предназначены для описания часто встречаемых в программах ошибок. Одним из таких классов является класс «ArgumentException».
Но в некоторых случаях, использовать уже имеющиеся классы для создания объектов при генерации исключений не получается, нет подходящих классов. В таком случае, программисту лучше написать собственный класс. Плюс ко всему, в собственном классе мы может создать дополнительные поля для хранения специфической информации. Например, кода ошибки. Вот пример такого класса:
//Класс, для описания пользовательского типа ошибок class PersonException : Exception //Используем наследование { //Принимает сообщение с описание ошибки, и код ошибки public PersonException(string aMessage, int aCode) : base(aMessage) //Вызываем конструктор базового класса { errorCode = aCode; } //Возвращает код ошибки public int ErrorCode { get { return errorCode; } } //Код ошибки private int errorCode; }
Как не сложно заметить, в примере приведенном выше, мы создали класс наследник класса «Exception» и расширили его полем «errorCode», которое хранит код ошибки. Так же, добавили свойство, возвращающее этот код, и создали конструктор, который принимает описание ошибки и её код. Причем, в конструкторе, мы вызываем конструктор базового класса, которому передаем сообщение об ошибке. Сгенерить исключение такого типа в конструкторе класса «Person» мы могли бы так:
//Конструктор public Person(string aName, int anAge) { name = aName; //Если указан отрицательный возраст if (anAge < 0) { throw new PersonException("Отрицательный возраст", 20); //Дальше, конструктор выполняться не будет... } age = anAge; }
А обрабатывать так:
try { Person somePerson = new Person("Иван", -21); } catch (PersonException ex) { //Обработка ошибок Console.WriteLine("Произошла ошибка: " + ex.Message + "; с кодом: " + ex.ErrorCode); }
Как видите, в блоке catch мы явно указали что он обрабатывает исключения типа «PersonException» и исключения других типов в него не попадут. В следующей статье, я хочу подробнее коснуться этой темы.
Добавить комментарий
Для отправки комментария вам необходимо авторизоваться.