Зачем реализовывать стандартные конструкторы исключений? - PullRequest
31 голосов
/ 31 мая 2009

Из MSDN, предупреждение анализа кода CA1032:

Exception types must implement the following constructors: <ul>
<li>public NewException() 
<li>public NewException(string) 
<li>public NewException(string, Exception) 
<li>protected or private NewException(SerializationInfo, StreamingContext)</ul>
Я понимаю цель конструктора сериализации, но есть ли смысл «требовать» других? Почему я не должен просто определять конструкторы, которые имеют смысл для использования моего исключения? Что если я никогда не захочу генерировать MyException без передачи сообщения - зачем мне определять конструктор без параметров? Что, если я хочу, чтобы MyException имел свойство int, и мне нужны только конструкторы, которые инициализируют это свойство?

Ответы [ 5 ]

11 голосов
/ 31 мая 2009

Вы получили несколько хороших ответов. Я просто хочу добавить, что предоставление этих дополнительных конструкторов не обязательно требует большого количества кода. Поскольку они уже реализованы в базовом классе, вы можете просто позволить этому выполнить свою работу:

public class MyCustomException : Exception
{
    public MyCustomException() : base() { }
    public MyCustomException(string message) : base(message) { }
    public MyCustomException(string message, Exception innerException) : base(message, innerException) { }
    // and so on...
}

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

11 голосов
/ 31 мая 2009

Это предупреждение, а не требование. Это в принципе принцип наименьшего удивления . Предоставление всех 4 облегчает использование ваших "обычных" исключений в C #. Если у вас есть веская причина игнорировать рекомендации, сделайте это. Но это нарушит некоторые сценарии использования и сделает ваш класс немного менее интуитивным.

3 голосов
/ 31 мая 2009

Реализация стандартных конструкторов исключений позволяет людям использовать ваше исключение стандартным, знакомым способом, который встроен во все существующие исключения .NET. Первые три могут быть необязательными, если по какой-то причине вы не хотите, чтобы один из них использовался (хотя почему вы хотели бы, чтобы я не мог этого понять.) Однако последний является конструктором десериализации, и если вы хотите ваше исключение должно поддерживаться в любой распределенной среде (.NET Remoting, ASP.NET Web Services, WCF и т. д.), тогда это очень важно.

Без конструктора десериализации и атрибута [Serializable] ваши исключения не будут работать в распределенной среде и могут вызвать другие проблемы. Учитывая это и аспект знакомства с опытными разработчиками C #, лучше всего реализовать как минимум 4 стандартных конструктора исключений и пометить ваши исключения с помощью [Serializable].

2 голосов
/ 31 мая 2009

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

Тот, который принимает другой Exception, позволяет связать все исключения через свойство InnerException.

Наконец, есть та, которая принимает строку сообщения, которая помогает использовать разумно согласованные исключения.

0 голосов
/ 31 мая 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...