Урок № 15. Детализация при обработке ошибок. Часть 2
Определение места возникновения ошибки
Доброго времени суток! В этом уроке я кратко расскажу о технике поиска места возникновения ошибок в компьютерных программах, написанных на C#. Для примера я буду использовать программу из предыдущего урока.
Сразу Вас «обрадую», почти всегда, на поиск причины и места возникновения ошибки уходит больше времени, чем на исправление самой ошибки.
Так вот, вернемся к делу! В предыдущем уроке мы научились определять причину возникновения ошибки, по той информации, которую предоставляет система (в нашем случае, дело было в том, что пользователь вводил не целочисленное значение, а какую-то другую строку). В этом же уроке, мы научимся определять место ее возникновения по косвенным признакам. И так, вспомним код программы из предыдущего урока:
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); } } }
А теперь результат работы программы при вводе некорректного значения:
Что мы видим на экране? Мы видим, что пользователю выведено приглашение ввести первое число. Программа обрабатывает ввод, и потом выполнение блока try прерывается, потому что видно, что дальше выполняется блок catch, т.е. блок обработки ошибок. Мы знаем, что за описанную функциональность (вывод приглашения, получение и обработка введенных данных), отвечает метод «GetNumber», который просто вызывается в блоке try. Соответственно, мы можем сделать вывод, что ошибка происходит именно в этом методе. Значит начинаем подробно разбирать его!
/* * Данный метод выводит пользователю приглашение, * указанное в аргументе anOutputStr, получает введенную * с клавиатуры строку, преобразует её в целое число и * возвращает это число */ static int GetNumber(string anOutputStr) { //Вывод приглашения пользователю Console.Write(anOutputStr); //Получение строки string tmpString = Console.ReadLine(); //Преобразование строки в число int tmpArg = Convert.ToInt32(tmpString); return tmpArg; }
Моделируем работу метода по шагам и ищем место, в котором его работа была прервана. Сначала должно быть выведено сообщение пользователю. Оно и было выведено, значит ошибка произошла где-то дальше! Соответственно, подозрение со строчки кода, представленной ниже, снимается:
//Вывод приглашения пользователю Console.Write(anOutputStr);
Идем дальше, за что отвечает следующая строка кода?
//Получение строки string tmpString = Console.ReadLine();
За получение данных после ввода их пользователем с клавиатуры и сохранения этих данных в переменной «tmpString». А теперь вспомним сообщение о причине ошибки. Там сказано, что входная строка имела некорректный формат. Вряд ли ошибка произошла во время выполнения текущего шага, ведь на нем строка просто считывается с клавиатуры и сохраняется в переменной, и не важно что ввел пользователь…Значит, идем дальше!
//Преобразование строки в число int tmpArg = Convert.ToInt32(tmpString);
На данном шаге, выполняется преобразование введенной строки в число. И вот тут, формат введенных данных уже имеет значение! Ведь не каждую строку можно преобразовать в число! Например слово «медведь» в число не преобразуешь! Тем более что у нас есть четкое требование, что число должно быть целым… Что накладывает еще большие ограничения на входные данные. Таким образом, мы понимаем, что ошибка произошла в строке кода:
//Преобразование строки в число int tmpArg = Convert.ToInt32(tmpString);
Вот мы и нашли место возникновения ошибки. А так как метод «GetNumber» вызывается дважды, то и ошибка может проявиться в двух случаях (в каком из них она произошла в нашем примере, догадаться не сложно по тем же косвенным признакам).
В подобных ситуациях можно найти различные выходы. Например, перед обработкой входных данных их можно сначала проверить, и в случае обнаружение какого-либо дефекта – запросить их еще раз. Или локализовать обработку исключительных ситуаций в пределах метода, в котором возникает ошибка и тому подобное. Но это уже разговор на другую, и к тому же весьма обширную, тему, которую мы оставим на будущее! А следующий урок будет чисто практический, что бы разгрузить Вас от потока информации…