Car myCar = new Car("Zippy", 20);
myCar.CrankTunes(true);
// Превышение допустимого максимума для скорости,
// чтобы генерировать исключение.
try {
for (int i = 0; i ‹ 10; i++) myCar.Accelerate(10);
} catch(Exception e) {
Console.WriteLine("\n ** * Ошибка! *** ");
Console.WriteLine("Метод: {0}", e.TargetSite);
Console.WriteLine("Сообщение: {0}", e.Message);
Console.WriteLine("Источник: {0}", е.Source);
}
// Ошибка обработана, выполняется следующий оператор.
Console.WriteLine("\n*** Выход из обработчика исключений *** ");
Console.ReadLine();
}
Блок try представляет собой набор операторов, которые могут генерировать иcключения в ходе их выполнения. Если обнаруживается исключение, поток выполнения программы направляется подходящему блоку catch. С другой стороны, если программный код в рамках блока try не генерирует исключений, блок catch полностью пропускается, и все проходит "тихо и спокойно". На рис. 6.2 показан вывод этой программы.
Как видите, после обработки исключения приложение может продолжать свою работу, начиная с оператора, следующего за блоком catch. В некоторых случаях исключение может оказаться достаточно серьезным для того, чтобы прекратить выполнение приложения. Но в большинстве случаев оказывается возможным исправить ситуацию в рамках программной логики обработчика исключений, чтобы приложение продолжило свою работу (хотя и с возможными ограничениями функциональности, если, например, не удается установить соединение с удаленным источником данных).
Рис. 6.2. Визуализация ошибок в рамках структурированной обработки исключений
Конфигурация состояния исключений
В настоящий момент конфигурация нашего объекта System.Exception задается в методе Accelerate(), где устанавливается значение, приписываемое свойству Message (через параметр конструктора). Но, как следует из табл. 6.1, класс Exception предлагает ряд дополнительных членов (TargetSite, StackTrace, HelpLink и Data), которые могут оказаться полезными в процессе дальнейшего анализа возникшей проблемы. Чтобы усовершенствовать наш пример, давайте рассмотрим содержимое указанных членов.
Свойство System.Exception.TargetSite позволяет выяснить дополнительную информацию о методе, генерирующем данное исключение. Как показано в предыдущем варианте метода Main(), при выводе значения TargetSite демонстрируется возвращаемое значение, имя и параметры метода, генерирующего данное исключение. Но TargetSite возвращает не просто строку, а строго типизированный объект System.Reflection.MethodBase. Этот тип содержит подробную информацию о методе, породившем проблему, и том классе, который определяет данный метод. Для иллюстрации обновим предыдущую логику catch так, как показано ниже.
static void Main(string[] args) {
…
// В действительности TargetSite возвращает объект MethodBase.
catch(Exception e) {
Console.WriteLine("\n*** Ошибка! ***");
Console.WriteLine("Имя члена: {0}", е.TargetSite);
Console.WriteLine("Класс, определяющий метод: {0}", е. TargetSite.DeclaringType);
Console.WriteLine("Тип члена: {0}", е. TargetSite.MemberType);
Console.WriteLine("Сообщение: {0}", e.Message);
Console.WriteLine("Источник: {0}", e.Source);
}
Console.WriteLine("\n*** Выход из обработчика исключений ***");
myCar.Accelerate(10); // Это не ускорит автомобиль.
Consolе.ReadLine();
}
На этот раз вы используете свойство MethodBase.DeclaringType, чтобы определить абсолютное имя класса, сгенерировавшего ошибку (в данном случае это класс SimpleException.Car), и свойство MemberType объекта MethodBase, чтобы идентифицировать тип породившего исключение члена (в том смысле, свойство это или метод). На рис. 6.3 показан обновленный вывод.
Рис 6.3. Получение информации о целевом объекте
Свойство System.Exception.StackTrace позволяет идентифицировать серию вызовов, которые привели к исключительной ситуации. Вы не должны устанавливать значение StackTrace, поскольку это делается автоматически в момент создания исключения. Для иллюстрации предположим, что мы снова обновили программный код catch.
catch (Exception e) {
…
Console.WriteLine(''Стек {0}", e.StackTrace);
}
Если выполнить программу теперь, то вы обнаружите, что на консоль будет выведен след стека (для вашего приложения номера строк и названия папок, конечно же, могут быть другими).
Читать дальше