В моем приложении мне нужно создать исключение, если свойство определенного класса имеет значение NULL или пусто (в случае, если это строка). Я не уверен, какое исключение лучше всего использовать в этом случае. Мне бы не хотелось создавать новое исключение, и я не уверен, подходит ли ArgumentNullException в этом случае.
Должен ли я создать новое исключение или есть исключение, которое я могу использовать?
Я не против выбросить ApplicationException.
Ответ 1 · рейтинг 70 · Joren
Рекомендации MSDN для стандартных исключений заявляет:
Использовать значение для имени параметра неявного значения средств установки свойств.
В следующем примере кода показано свойство, которое вызывает исключение, если вызывающий объект передает нулевой аргумент.
public IPAddress Address
{
get
{
return address;
}
set
{
if(value == null)
{
throw new ArgumentNullException("value");
}
address = value;
}
}
Кроме того, в рекомендациях MSDN по проектированию собственности говорится :
Избегайте создания исключений из методов получения свойств.
Получатели свойств должны быть простыми операциями без каких-либо предварительных условий. Если получатель может вызвать исключение, подумайте о том, чтобы преобразовать свойство в метод. Эта рекомендация не относится к индексаторам. Индексаторы могут вызывать исключения из-за недопустимых аргументов.
Выдавать исключения из средства задания свойств допустимо и допустимо.
Так что бросьте ArgumentNullException в сеттер на null и ArgumentException на пустую строку и ничего не делайте в геттере. Поскольку сеттер выбрасывает, и только у вас есть доступ к резервному полю, легко убедиться, что оно не будет содержать недопустимое значение. Бросок геттера тогда бессмыслен. Однако это может быть хорошим местом для использования _5 _.
Если вы действительно не можете указать подходящее значение по умолчанию, я полагаю, у вас есть три варианта:
Просто верните все, что находится в свойстве, и задокументируйте это поведение как часть контракта на использование. Позвольте вызывающему абоненту разобраться с этим. Вы также можете потребовать допустимое значение в конструкторе. Однако это может быть совершенно неподходящим для вашего приложения.
Замените свойство методами: метод установки, который выдает, когда передано недопустимое значение, и метод получения, который выдает InvalidOperationException, когда свойству никогда не было присвоено допустимое значение.
Выбросьте InvalidOperationException из получателя, так как вы могли бы считать, что "свойство никогда не назначалось" недопустимым состоянием. Хотя обычно вы не должны выбрасывать из геттеров, я полагаю, что это может быть хорошей причиной для исключения.
Если вы выбираете варианты 2 или 3, вы также должны включить метод TryGet-, который возвращает bool, который указывает, установлено ли для свойства допустимое значение, и если да, возвращает это значение в параметре out. В противном случае вы заставляете вызывающих абонентов быть подготовленными к обработке InvalidOperationException, если они предварительно сами не установили свойство и, следовательно, не знают, что оно не будет сгенерировано. Сравните int.Parse с int.TryParse.
Я бы предложил использовать вариант 2 с методом TryGet. Он не нарушает никаких правил и предъявляет минимальные требования к вызывающему коду.
О других предложениях
ApplicationException является слишком общим. ArgumentException является слишком общим для null, но в остальном подходит. снова документы MSDN :
Выбрасывайте наиболее конкретное (наиболее производное) подходящее исключение. Например, если метод получает аргумент null (Nothing в Visual Basic), он должен генерировать исключение System.ArgumentNullException вместо своего базового типа System.ArgumentException.
На самом деле вы вообще не должны использовать ApplicationException (документы):
Создавайте настраиваемые исключения из класса T: System.Exception, а не из класса T: System.ApplicationException.
Первоначально предполагалось, что настраиваемые исключения должны быть производными от класса ApplicationException; однако было обнаружено, что это не добавляет значительной ценности. Для получения дополнительной информации см. Рекомендации по обработке исключений.
InvalidOperationException предназначен не для случаев, когда аргументы метода или свойства недопустимы, а для случаев, когда операция в целом недопустима (документы). Его не следует выкидывать из сеттера:
Выбрасывайте исключение System.InvalidOperationException, если оно находится в несоответствующем состоянии. System.InvalidOperationException следует вызывать, если набор свойств или вызов метода не подходят для текущего состояния объекта. Например, запись в System.IO.FileStream, открытый для чтения, должна вызывать исключение System.InvalidOperationException.
Между прочим, InvalidOperationException используется, когда операция недопустима для текущего состояния объекта. Если операция всегда недопустима для всего класса, следует использовать _ 19_.
Ответ 3 · рейтинг 2 · John Fisher
Что ж, это не аргумент, если вы ссылаетесь на свойство класса. Итак, вам не следует использовать ArgumentException или ArgumentNullException.
NullReferenceException произойдет, если вы просто оставите все как есть, поэтому я предполагаю, что это не то, что вы ищете.
Итак, использование ApplicationExeption или InvalidOperationException, вероятно, будет вашим лучшим выбором, не забудьте указать значимую строку для описания ошибки.
Ответ 6 · рейтинг 1 · JaredPar
Если проблема в том, что член аргумента, а не сам аргумент, имеет значение NULL, то я думаю, что лучшим выбором будет более общий ArgumentException. ArgumentNullException здесь не работает, потому что аргумент не равен нулю. Вместо этого вам нужен более общий тип исключения "что-то не так с вашим аргументом".
Здесь было бы очень уместно подробное сообщение для конструктора
Ответ 7 · рейтинг 1 · James Black
Если он не может быть нулевым или пустым, пусть ваш установщик не допускает нулевые или пустые значения или генерирует исключение ArgumentException, если это так.
Также потребуйте, чтобы свойство было установлено в конструкторе.
Таким образом, вы устанавливаете допустимое значение, вместо того, чтобы возвращаться позже и говорить, что вы не можете определить баланс учетной записи, поскольку учетная запись не настроена.
Но я бы согласился с ответом bduke.