{
HelpLink = "http://www.CarsRUs.com",
Data = {
{"TimeStamp",$"The car exploded at {DateTime.Now}"},
{"Cause","You have a lead foot."}
}
};
}
Console.WriteLine("=> CurrentSpeed = {0}", CurrentSpeed);
}
}
С целью успешного прохода по парам "ключ-значение" добавьте директиву
using
для пространства имен
System.Collections
, т.к. в файле с операторами верхнего уровня будет применяться тип
DictionaryEntry
:
using System.Collections;
Затем обновите логику в блоке
catch
, чтобы обеспечить проверку значения, возвращаемого из свойства
Data
, на равенство
null
(т.е. стандартному значению). После этого свойства
Key
и
Value
типа
DictionaryEntry
используются для вывода специальных данных на консоль:
catch (Exception e)
{
...
Console.WriteLine("\n-> Custom Data:");
foreach (DictionaryEntry de in e.Data)
{
Console.WriteLine("-> {0}: {1}", de.Key, de.Value);
}
}
Вот как теперь выглядит финальный вывод программы:
***** Simple Exception Example *****
=> Creating a car and stepping on it!
Jamming...
=> CurrentSpeed = 30
=> CurrentSpeed = 40
=> CurrentSpeed = 50
=> CurrentSpeed = 60
=> CurrentSpeed = 70
=> CurrentSpeed = 80
=> CurrentSpeed = 90
*** Error! ***
Member name: Void Accelerate(Int32)
Class defining member: SimpleException.Car
Member type: Method
Message: Zippy has overheated!
Source: SimpleException
Stack: at SimpleException.Car.Accelerate(Int32 delta) ...
at SimpleException.Program.Main(String[] args) ...
Help Link: http://www.CarsRUs.com
-> Custom Data:
-> TimeStamp: The car exploded at 3/15/2020 16:22:59
-> Cause: You have a lead foot.
***** Out of exception logic *****
Свойство
Data
удобно в том смысле, что оно позволяет упаковывать специальную информацию об ошибке, не требуя построения нового типа класса для расширения базового класса
Exception
. Тем не менее, каким бы полезным ни было свойство
Data
, разработчики все равно обычно строят строго типизированные классы исключений, которые поддерживают специальные данные, применяя строго типизированные свойства.
Такой подход позволяет вызывающему коду перехватывать конкретный тип, производный от
Exception
, а не углубляться в коллекцию данных с целью получения дополнительных деталей. Чтобы понять, как это работает, необходимо разобраться с разницей между исключениями уровня системы и уровня приложения.
Исключения уровня системы (System.SystemException)
В библиотеках базовых классов .NET 5 определено много классов, которые в конечном итоге являются производными от
System.Exception
.
Например, в пространстве имен
System
определены основные объекты исключений, такие как
ArgumentOutOfRangeException
,
IndexOutOfRangeException
,
StackOverflowException
и т.п. В других пространствах имен есть исключения, которые отражают поведение этих пространств имен. Например, в
System.Drawing.Printing
определены исключения, связанные с печатью, в
System.IO
— исключения, возникающие во время ввода-вывода, в
System.Data
— исключения, специфичные для баз данных, и т.д.
Исключения, которые генерируются самой платформой .NET 5, называются системными исключениями. Такие исключения в общем случае рассматриваются как неисправимые фатальные ошибки. Системные исключения унаследованы прямо от базового класса
System.SystemException
, который в свою очередь порожден от
System.Exception
(а тот — от класса
System.Object
):
public class SystemException : Exception
{
// Various constructors.
}
Учитывая, что тип
System.SystemException
не добавляет никакой дополнительной функциональности кроме набора специальных конструкторов, вас может интересовать, по какой причине он вообще существует. Попросту говоря, когда тип исключения является производным от
System.SystemException
, то есть возможность выяснить, что исключение сгенерировала исполняющая среда .NET 5, а не кодовая база выполняющегося приложения. Это довольно легко проверить, используя ключевое слово
is
:
// Верно! NullReferenceException является SystemException.