Язык программирования C#9 и платформа .NET5
Шрифт:
public CarIsDeadException(string cause, DateTime time,
string message, System.Exception
inner) :
base(message, inner)
{
CauseOfError = cause;
ErrorTimeStamp = time;
}
}
Затем необходимо модифицировать метод
Accelerate
с учетом обновленного специального исключения:
throw new CarIsDeadException("You have a lead foot",
DateTime.Now,$"{PetName} has overheated!")
{
HelpLink = "http://www.CarsRUs.com",
};
Поскольку
ехс
и нажмите клавишу <ТаЬ> (в Visual Studio нажмите <Tab> два раза). Обработка множества исключений
В своей простейшей форме блок
try
сопровождается единственным блоком catch
. Однако в реальности часто приходится сталкиваться с ситуациями, когда операторы внутри блока try
могут генерировать многочисленные исключения. Создайте новый проект консольного приложения на C# по имени ProcessMultipleExpceptions
, скопируйте в него файлы Car.cs
, Radio.cs
и CarIsDeadException.cs
из предыдущего проекта CustomException
и надлежащим образом измените название пространства имен. Затем модифицируйте метод
Accelerate
класса Car
так, чтобы он генерировал еще и предопределенное в библиотеках базовых классов исключение ArgumentOutOfRangeException
, если передается недопустимый параметр (которым будет считаться любое значение меньше нуля). Обратите внимание, что конструктор этого класса исключения принимает имя проблемного аргумента в первом параметре типа string
, за которым следует сообщение с описанием ошибки.
// Перед продолжением проверить аргумент на предмет допустимости.
public void Accelerate(int delta)
{
if (delta < 0)
{
throw new ArgumentOutOfRangeException(nameof(delta),
"Speed must be greater than zero");
// Значение скорости должно быть больше нуля!
}
...
}
На заметку! Операция
nameof
возвращает строку, представляющую имя объекта, т.е. переменную delta
в рассматриваемом примере. Такой прием позволяет безопасно ссылаться на объекты, методы и переменные С#, когда требуются их строковые версии. Теперь логика в блоке
catch
может реагировать на каждый тип исключения специфическим образом:
using System;
using System.IO;
using ProcessMultipleExceptions;
Console.WriteLine("***** Handling Multiple Exceptions *****\n");
Car myCar = new Car("Rusty", 90);
try
{
// Вызвать исключение выхода за пределы диапазона аргумента.
myCar.Accelerate(-10);
}
catch (CarIsDeadException e)
{
Console.WriteLine(e.Message);
}
catch (ArgumentOutOfRangeException e)
{
Console.WriteLine(e.Message);
}
Console.ReadLine;
При
написании множества блоковcatch
вы должны иметь в виду, что когда исключение сгенерировано, оно будет обрабатываться первым подходящим блоком catch
. Чтобы проиллюстрировать, что означает "первый подходящий" блок catch
, модифицируйте предыдущий код, добавив еще один блок catch
, который пытается обработать все остальные исключения кроме CarIsDeadException
и ArgumentOutOfRangeException
путем перехвата общего типа System.Exception
:
// Этот код не скомпилируется!
Console.WriteLine("***** Handling Multiple Exceptions *****\n");
Car myCar = new Car("Rusty", 90);
try
{
// Вызвать исключение выхода за пределы диапазона аргумента.
myCar.Accelerate(-10);
}
catch(Exception e)
{
// Обработать все остальные исключения?
Console.WriteLine(e.Message);
}
catch (CarIsDeadException e)
{
Console.WriteLine(e.Message);
}
catch (ArgumentOutOfRangeException e)
{
Console.WriteLine(e.Message);
}
Console.ReadLine;
Представленная выше логика обработки исключений приводит к возникновению ошибок на этапе компиляции. Проблема в том, что первый блок
catch
способен обрабатывать любые исключения, производные от System.Exception
(с учетом отношения "является"), в том числе CarIsDeadException
и ArgumentOutOfRangeException
. Следовательно, два последних блока catch
в принципе недостижимы! Запомните эмпирическое правило: блоки
catch
должны быть структурированы так, чтобы первый catch
перехватывал наиболее специфическое исключение (т.е. производный тип, расположенный ниже всех в цепочке наследования типов исключений), а последний catch
— самое общее исключение (т.е. базовый класс имеющейся цепочки наследования: System.Exception
в данном случае). Таким образом, если вы хотите определить блок
catch
, который будет обрабатывать любые исключения помимо CarIsDeadException
и ArgumentOutOfRangeException
, то можно было бы написать следующий код:
// Этот код скомпилируется без проблем.
Console.WriteLine("***** Handling Multiple Exceptions *****\n");
Car myCar = new Car("Rusty", 90);
try
{
// Вызвать исключение выхода за пределы диапазона аргумента.
myCar.Accelerate(-10);
}
catch (CarIsDeadException e)
{
Console.WriteLine(e.Message);
Поделиться с друзьями: