Урок № 14. Детализация при обработке ошибок. Часть 1


Детализация при обработке ошибок (исключительных ситуаций)

Доброго времени суток! Настало время еще раз поговорить про обработку ошибок, или исключительных ситуаций, которые могут возникать в наших программах. Мы уже касались этой темы, в том числе и в предыдущем уроке мы использовали механизм обработки ошибок. Давайте вспомним код заключительного примера предыдущего урока:

class Program
{
    /*
    * Данный метод выводит пользователю приглашение,
    * указанное в аргументе anOutputStr, получает введенную
    * с клавиатуры строку, преобразует её в целое число и
    * возвращает это число
    */
    static int GetNumber(string anOutputStr)
    {
        //Вывод приглашения пользователю
        Console.Write(anOutputStr);

        //Получение строки
        string tmpString = Console.ReadLine();

        //Преобразование строки в число
        int tmpArg = Convert.ToInt32(tmpString);

        return tmpArg;
    }

    static void Main(string[] args)
    {
        //Потенциально опасный блок
        try
        {
            //Первый вызов метода (получение первого числа)
            int firstArg = GetNumber("Введите первое число и нажмите клавишу Enter: ");

            //Второй вызов метода (получение второго числа)
            int secondArg = GetNumber("Введите второе число и нажмите клавишу Enter: ");

            //Сложение двух переменных
            int result = firstArg + secondArg;

            //Вывод результата
            Console.WriteLine("Результат сложения введенных чисел: " + result.ToString());
        }
        //Блок обработки ошибок, SystemException - самый общий тип ошибок
        catch (SystemException)
        {
            Console.WriteLine("Во время выполнения программы произошла ошибка, вероятно, были введены некорректные данные!");
        }
    }
}

Мы видим, что у нас в программе есть блок потенциально опасного кода (это блок try) и есть блок, который отвечает за обработку ошибок (это блок catch).

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

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

Так как же нам получать больше информации в таких ситуациях? Выход есть! Дело в том, что мы использовали блок обработки ошибок неполноценно! Мы так сказать, не переходили на «личности», в круглых скобках после слова catch мы всего лишь указали тип ошибок (если хотите, класс ошибок), которые обрабатывает это блок.

А теперь я покажу, как можно модифицировать блок обработки ошибок (измененные и добавленные строки выделены):

 
//Блок обработки ошибок, SystemException - самый общий тип ошибок 
catch (SystemException ex) 
{ 
    Console.WriteLine("Во время выполнения программы произошла ошибка, вероятно, были введены некорректные данные!"); 
    
    //Вывод в консоль информации о причине ошибки 
    Console.WriteLine("Причина ошибки: " + ex.Message); 
} 

Что же изменилось? Я добавил объект в круглых скобках после ключевого слова catch, раньше мы указывали там только тип, а теперь мы указали еще и конкретный объект. Эта ситуация схожа указанием формальных параметров в методах (аргументов методов), и теперь, при возникновении ошибки, система не только передаст управление блоку catch, но и «запакует» необходимую информацию по ошибке в объект «ex», к которому мы имеем доступ внутри блока catch. И второе что я сделал, я воспользовался свойством «Message» объекта «ex». В нем хранится системное описание ошибки.

Если Вы модифицируете пример (а точнее блок обработки ошибок) из предыдущего урока как я показывал ранее, у Вас получится примерно следующее:

class Program
{
    /*
    * Данный метод выводит пользователю приглашение,
    * указанное в аргументе anOutputStr, получает введенную
    * с клавиатуры строку, преобразует её в целое число и
    * возвращает это число
    */
    static int GetNumber(string anOutputStr)
    {
        //Вывод приглашения пользователю
        Console.Write(anOutputStr);

        //Получение строки
        string tmpString = Console.ReadLine();

        //Преобразование строки в число
        int tmpArg = Convert.ToInt32(tmpString);

        return tmpArg;
    }

    static void Main(string[] args)
    {
        //Потенциально опасный блок
        try
        {
            //Первый вызов метода (получение первого числа)
            int firstArg = GetNumber("Введите первое число и нажмите клавишу Enter: ");

            //Второй вызов метода (получение второго числа)
            int secondArg = GetNumber("Введите второе число и нажмите клавишу Enter: ");

            //Сложение двух переменных
            int result = firstArg + secondArg;

            //Вывод результата
            Console.WriteLine("Результат сложения введенных чисел: " + result.ToString());
        }
        //Блок обработки ошибок, SystemException - самый общий тип ошибок
        catch (SystemException ex)
        {
            Console.WriteLine("Во время выполнения программы произошла ошибка, вероятно, были введены некорректные данные!");

            //Вывод в консоль информации о причине ошибки
            Console.WriteLine("Причина ошибки: " + ex.Message);
        }
    }
}

И если вы соберете проект и запустите программу, после чего введете некорректные данные (например, не целое число), т.е. спровоцируете ошибку, то получите нечто похожее:

Работы программы, при вводе некорректных данных

Работы программы, при вводе некорректных данных

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

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

Перейти к следующему уроку