Генерация исключений, а нужно ли?

На самом деле очень расплывчатый вопрос, начнем с того, а какие именно исключения? Ведь есть те, которые создаются и обрабатывается непосредственно в среде CLR(в дальнейшем управляемые), а есть те, которые вызываются вне среды CLR(в дальнейшем неуправляемые), например, ошибки доступа к памяти, деления на ноль на уровне процессора, аварийные остановки и т.д.

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

Приведем пример операции деления на 0. У нас здесь два варианта:

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

Сама операция генерации исключения - довольно дорогостоящая, порой она может ставить палки в колеса быстродействию нашей программы, можем ли мы исправить эту ситуацию?

В зависимости от ситуации…

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

int a = 10;
int b = 0;

if (b != 0)
{
    int result = a / b;
    Console.WriteLine("Result: " + result);
    return;
}
    Console.WriteLine("Error: Division by zero is not allowed.");

Аналогичной ситуация может быть и с NullReferenceException, перед обращением к объекту, мы можем сравнивать экземпляр объекта с null. Но такие простые примеры не могут быть показательными, в конце концов разработка продукта более масштабная, сложная и запутанная, метод может генерировать 5 и более исключений, всех их заранее просчитать может не получится( допустим мы вызвали метод вообще из другой библиотеки, реализация которой нам не известна), но используя такой обход генераций простых исключений, наложенный на многие участки в проекте, может помочь нам в поддержании быстродействии приложения.

А что по поводу неуправляемых?

Неуправляемые исключения

Как было сказано в начале, это те исключения, которые вызываются вне среды CLR. Неуправляемые исключения не наследуются от класса System.Exception и не могут быть обработаны с помощью блоков try-catch.

В случае возникновения неуправляемого исключения, среда CLR пытается преобразовать его в управляемое (вызывая метод RuntimeWrapper.ThrowException(Object)), и если преобразование не удается, среда CLR завершает работу приложения, причем стоит учитывать, что успешность преобразования прямо зависит от версии .NET.

Настоятельно рекомендую ознакомится с докладом DOTNEXT Евгения Пешкова

Но что с исключением StackOverflowException? Как видим из документации, оно у нас управляемое, и перехватывать мы умеем… верно?…

Мы не можем перехватить исключение переполнения стека, потому что коду, отвечающему за перехват исключения может самому понадобится память в стеке, а он переполнен…

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

Итог

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

Надеюсь пост был для вас познавательным, до новых встреч!