C#. Почему нужно создавать собственные классы исключений и как это правильно делать

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

В .NET Framework предусмотрен довольно мощный механизм работы с исключениями, основанный на классе Exception.

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

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

throw new Exception("My Exception!");

Однако так делать не стоит и вот почему.

Идентификация исключительной ситуации

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

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

try
{
    // Делаем что-то
}
catch (Exception ex)
{
    // Делаем что-то
}

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

try
{
    // Делаем что-то
}
catch (MyException1 ex)
{
    // Делаем что-то
}
catch (MyException2 ex)
{
    // Делаем что-то
}

Расширенное представление исключительной ситуации

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

Описание своего класса для исключения

Рассмотрим пример создания простейшего класса исключения. Это класс должен соответствовать следующим требованиям:

  • Быть наследником класса Exception (необязательно непосредственным);
  • Поддерживать сериализацию;
  • Содержать набор из четырёх конструкторов.

Ниже приведён код класса исключения, соответствующий всему вышеперечисленному:

using System;
using System.Runtime.Serialization;
namespace MyNameSpace
{
    [System.Serializable]
    class MyException:Exception
    {
        public MyException () { }
        public MyException (string message) : base(message) { }
        public MyException (string message, Exception inner) : base(message, inner) { }
        protected MyException (SerializationInfo info, StreamingContext context) : base(info, context) { }
    }
}

Этот класс совсем небольшой. В нём практически ничего нет, и его не составит труда создать любому программисту. Но, даже этого уже достаточно для представления любой исключительной ситуации.

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

В качестве примера добавим поле, которое будет хранить значение переменной в случае возникновения ошибки.

using System;
using System.Runtime.Serialization;
namespace Exc
{
    [System.Serializable]
    class MyException:Exception
    {
        private object _value;
        public MyException() { }
        public MyException(string message) : base(message) { }
        public MyException(string message, Exception inner) : base(message, inner) { }
        protected MyException(SerializationInfo info, StreamingContext context) : base(info, context) { }
        public MyException(string message, object value) : base(message)
        {
            _value = value;
        }
        public object Value
        {
            get { return _value; }
        }
    }
}

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

private static void TestMethod()
{
    string s = "abc";
    throw new MyException("Ошибка", s);
}

Обработка исключения:

try
{
    TestMethod();
}
catch(MyException ex)
{
    label1.Text = ex.Value.ToString();
}

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *