Подтвердить что ты не робот

Свойство System.Exception.Data

Класс System.Exception(фактически любое исключение) имеет свойство Data, которое почти всегда пусто. Если выбрасывать исключения, должно ли это поле быть полезным? Или у меня есть внутреннее использование, о котором я не знаю?

4b9b3361

Ответ 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); }
    }
}