В своей простейшей форме блок try
catch
. Однако в реальности часто приходится сталкиваться с ситуациями, когда операторы внутри блока try
могут генерировать 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
в данном случае).