ре:разработка пользовательских исключений:должен ли я реализовать конструктор по умолчанию?конструктор “внутреннего исключения”?

StackOverflow https://stackoverflow.com/questions/1068103

Вопрос

Ответ на Каков правильный способ сделать исключения сериализуемыми? говорит, что "правильная" базовая реализация для пользовательского исключения включает в себя 4 ctors:

[Serializable]
public class SerializableExceptionWithoutCustomProperties : Exception
{
    public SerializableExceptionWithoutCustomProperties()
    {
    }

    public SerializableExceptionWithoutCustomProperties(string message) 
        : base(message)
    {
    }

    public SerializableExceptionWithoutCustomProperties(string message, Exception innerException) 
        : base(message, innerException)
    {
    }

    // Without this constructor, deserialization will fail
    protected SerializableExceptionWithoutCustomProperties(SerializationInfo info, StreamingContext context) 
        : base(info, context)
    {
    }
}

Сразу скажу, я бы сказал, что это действительно плохое название для типа Исключения.Но, помимо этого,

  1. Для целей двоичной сериализации, к которой относился вопрос SO, должен ли я реализовать все 4 конструктора?Я думаю, что для целей [Serializable] я должен предоставить ctor, который принимает 2 аргумента типа (SerializationInfo, StreamingContext), потому что исключение происходит из System.Исключение, которое само выполняет пользовательскую сериализацию.Я могу это понять.Но должен ли я внедрять другие ctors, для того, чтобы правильно предоставить сериализуемое исключение?Я знаю, что если я хочу разрешить типу быть xml-сериализуемым, мне нужно указать ctor по умолчанию (без операции).Верно ли то же самое для [Serializable]?На мгновение давайте ограничимся узкой проблемой [Serializable] и оставим в стороне любые более широкие рекомендации, касающиеся "дизайна фреймворка".

  2. Переходя к более широкому вопросу: В руководящих принципах говорится это пользовательские исключения должны реализовывать 4 общих ctors.Каковы доводы, стоящие за этим руководством?Если я создам пользовательское исключение, действительно ли это плохие манеры или даже ошибка, если я не предоставлю ctor null / default?Действительно ли это плохие манеры или даже ошибка, если я не предоставляю ctor, который допускает исключение InnerException?Почему?Рассмотрим случай, когда мое пользовательское исключение генерируется в коде моей библиотеки, и единственные экземпляры, которые я когда-либо генерирую, включают сообщение и не содержат InnerException.

  3. Короче говоря, является ли следующий код приемлемым для пользовательского исключения, которое не предоставляет никаких дополнительных свойств?


[Serializable]
public class CustomException : Exception
{
    public CustomException(string message) : base(message) { }

    // Without this constructor, deserialization will fail
    protected CustomException(SerializationInfo info, StreamingContext context) 
        : base(info, context) { }
}

смотрите также: Блог Winterdom:Сделайте исключения Сериализуемыми.

Это было полезно?

Решение 4

Мне не понравился ни один из ответов.Я останавливаюсь на предложенном мной решении, которое таково..что я могу исключить "обычные" конструкторы в моем пользовательском исключении, включая конструктор по умолчанию и вложенный конструктор.Кроме того, мне нужно убедиться, что сериализация работает из-за вызовов между доменами приложений.

Другие советы

Соответствующим предупреждением при анализе кода является CA1032, а справочная страница обеспечивает это обоснование:

Непредоставление полного набора конструкторов может затруднить корректную обработку исключений.Например, конструктор с сигнатурой NewException(строка, Исключение) используется для создания исключений, которые вызваны другими исключениями.Без этого конструктора вы не сможете создать и выдать экземпляр вашего пользовательского исключения, который содержит внутреннее (вложенное) исключение, что и должен делать управляемый код в такой ситуации.Первые три конструктора исключений являются общедоступными по соглашению.Четвертый конструктор защищен в незапечатанных классах и приватен в закрытых классах.

Только вы или ваша проектная команда можете решить, требует ли ваша ситуация исключения (извините ...)

Эй, я знаю, что это, по крайней мере, рекомендовано Microsoft.Если вы используете VS2008 (или, возможно, более ранние версии), вы можете легко позволить Visual Studio создать их для вас, набрав

exception

заходим в редактор и нажимаем Tab (дважды?).Это создаст их, давая вам возможность присвоить классу новое имя.

Предложение:если другие будут использовать ваше исключение, и поскольку эти другие будут знакомы с .NET exceptions, то почему бы просто не следовать рекомендациям?Они те же, что используются .NET Framework.

Вам не кажется, что это слишком большая работа, учитывая количество пользовательских типов исключений, которые вы определяете?Если это так, то это было бы еще одной причиной следовать рекомендациям, в которых указано, что вам не следует создавать большое количество пользовательских исключений.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top