Ответ 1
Руководства MSDN для стандартных исключений:
Использовать значение для имени параметра неявного значения свойства сеттеры.
В следующем примере кода показан свойство, которое генерирует исключение, если вызывающий объект передает нулевой аргумент.
public IPAddress Address { get { return address; } set { if(value == null) { throw new ArgumentNullException("value"); } address = value; } }
Кроме того, Руководства MSDN для дизайна свойств говорят:
Избегайте бросать исключения из свойство getters.
Убиратели свойств должны быть простыми операций без каких-либо предварительных условий. Если геттер может выбросить исключение, рассмотрите вопрос о перепроектировании быть методом. Эта рекомендация не применяются к индексаторам. Индексаторы могут исключить из-за недействительности Аргументы.
Действительно и допустимо бросать исключения из средства настройки свойств.
Итак, бросьте ArgumentNullException
в сеттер на null
и ArgumentException
на пустой строке и ничего не сделайте в получателе. Поскольку сеттер выбрасывает и только у вас есть доступ к полю резервного копирования, легко убедиться, что он не будет содержать недопустимое значение. Наличие геттер-броска тогда бессмысленно. Это может быть хорошим местом для использования Debug.Assert
.
Если вы действительно не можете предоставить соответствующий по умолчанию, то, полагаю, у вас есть три варианта:
-
Просто верните все, что есть в свойстве, и запишите это поведение как часть контракта на использование. Позвольте собеседнику справиться с этим. Вы также можете потребовать действительное значение в конструкторе. Это может быть совершенно неприемлемо для вашего приложения.
-
Заменить свойство методами: метод setter, который генерирует при передаче недопустимого значения, и метод getter, который выдает
InvalidOperationException
, когда свойство никогда не было присвоено действительное значение. -
Бросьте
InvalidOperationException
из получателя, так как вы можете считать, что свойство никогда не было назначено недопустимым. Хотя вы, как правило, не должны бросать из геттеров, я полагаю, это может быть хорошей причиной для исключения.
Если вы выберете варианты 2 или 3, вы также должны включить метод TryGet, который возвращает bool
, который указывает, было ли свойство установлено на допустимое значение, и если это так возвращает это значение в параметре out
, В противном случае вы вынуждаете вызывающих абонентов быть готовыми к обработке InvalidOperationException
, если только они ранее не установили свойство самостоятельно и, следовательно, знали, что он не выбрасывает. Сравните int.Parse
и int.TryParse
.
Я бы предложил использовать вариант 2 с помощью метода TryGet. Он не нарушает никаких рекомендаций и предъявляет минимальные требования к вызывающему коду.
О других предложениях ApplicationException
является слишком общим. ArgumentException
является слишком общим для null
, но в остальном это не так. Документы MSDN снова:
Выбрасывать наиболее специфическое (наиболее производное) исключение, которое подходящее. Например, если метод получает нуль (Nothing in Visual Основной) аргумент, он должен бросить Вместо System.rgumentNullException его базового типа System.ArgumentException.
На самом деле вам не следует использовать ApplicationException
вообще (docs):
Вывод пользовательских исключений из класса T: System.Exception, а не класса T: System.ApplicationException.
Первоначально предполагалось, что пользовательские исключения должны выводиться из класса ApplicationException; однако, как было установлено, это не означает значительную ценность. Дополнительные сведения см. В разделе "Рекомендации по устранению исключений".
InvalidOperationException
предназначен не для тех случаев, когда аргументы метода или свойства недействительны, но если операция в целом недействительна ( "Документы" ). Его нельзя выбрасывать из сеттера:
Выбрасывать исключение System.InvalidOperationException, если оно находится в неудовлетворительном состоянии. System.InvalidOperationException должно быть выбрано, если набор свойств или вызов метода не подходят, учитывая текущее состояние объекта. Например, запись в System.IO.FileStream, который был открыт для чтения, должен генерировать исключение System.InvalidOperationException.
Кстати, InvalidOperationException
означает, что операция недействительна для текущего состояния объекта. Если операция всегда недействительна для всего класса, вы должны использовать NotSupportedException
.