Класс System.Exception(фактически любое исключение) имеет свойство Data, которое почти всегда пусто. Если выбрасывать исключения, должно ли это поле быть полезным? Или у меня есть внутреннее использование, о котором я не знаю?
Свойство System.Exception.Data
Ответ 1
Документация кажется достаточно понятной относительно ее использования (выделено мной):
Получает набор пар ключ/значение, которые предоставляют дополнительную пользовательскую информацию об исключении.
Почему он существует в первую очередь? Я предполагаю, что та же самая причина Control
имеет свойство Tag
. В ранние дни .NET(до того, как каждый программист Боб и Бетти понял объекты и наследование), они хотели сделать API достаточно простым, чтобы каждый мог понять, как добавить дополнительные данные к вещам.
Тем не менее, точка создания пользовательских исключений, полученных из System.Exception
, необязательно должна включать дополнительную информацию, но чтобы клиент мог ограничивать исключения, которые они улавливают, только тем, с которыми они могут обращаться. Если они знают, как обрабатывать набор определенных исключений, которые может выполнять ваш код, они должны иметь возможность только перехватывать эти исключения, не перехватывая базовый класс System.Exception
. То, что вы, безусловно, никогда не должны делать, - это требование, чтобы клиентский код обнаруживал неспецифический класс исключения и читал свойство, чтобы определить, какой тип исключения он (и, следовательно, может ли он справиться с ним).
Я честно никогда не использовал эту собственность раньше. Я должен был проверить документацию, даже чтобы увидеть, что она действительно существует. Но я считаю, что это наиболее полезно для реализации пользовательских журналов исключений. Вы можете встроить много важной информации в свойство Data
(независимо от уровня вывода класса исключения), а затем передать это в свой код регистрации. Отражатель указывает, что он используется внутри в нескольких местах именно для этой цели. Также приятно, что вся предоставленная вами информация корректно сериализуется для вас автоматически.
Ответ 2
Еще одно замечание, что я делаю, когда я наследую исключение и добавляю свойства, заключается в том, чтобы заставить свойства действительно получать и устанавливать из словаря данных, а не из локальных переменных.
[Serializable]
public class PacketParseException : Exception
{
public byte[] ByteData
{
get
{
return (byte[])this.Data["ByteData"];
}
}
public PacketParseException(string message, byte[] data, Exception inner) : base(message, inner)
{
this.Data.Add("ByteData", data);
}
}
То, как я это вижу, тогда внутренние данные доступны также из Exception, например, при регистрации, поэтому нет необходимости использовать для фактического типа.
Ответ 3
С новым CallerMemberNameAttribute
еще проще использовать свойство Data
для хранения:
public class BetterException : Exception
{
protected T GetValue<T>([CallerMemberNameAttribute] string propertyName = "")
{
return (T)Data[propertyName];
}
protected void SetValue<T>(T value, [CallerMemberNameAttribute] string propertyName = "")
{
Data[propertyName] = value;
}
}
Использование:
class MyException : BetterException
{
public MyException(string name)
{
Name = name;
}
public string Name
{
get { return GetValue<string>(); }
set { SetValue(value); }
}
}