Когда использовать новый тип исключения
Каковы рекомендации по созданию нового типа исключения вместо использования одного из встроенных исключений в .Net?
Проблема, которая заставляла меня думать, такова. У меня есть служба WCF, которая является базовой службой ввода-вывода. Если служба не может создать вывод, потому что вход недействителен, я хочу выставить исключение, но какой?
Сейчас я просто бросаю system.Exception, но это мне не подходит, я не знаю, почему, это просто неправильно.
Одна вещь, которая меня пугает, если я тестирую ее с помощью unit test, и я ожидаю, что система будет исключена. Исключение. Исключение могло также быть выброшено каркасом или другим кодом, а не кодом, который я исключал, чтобы бросить. Затем тест пройдет, так как я получу ожидаемое исключение, но оно должно потерпеть неудачу.
Что вы рекомендуете?
Ответы
Ответ 1
Избегайте бросать System.Exception
или System.ApplicationException
самостоятельно, так как они слишком общие.
Для служб WCF существуют Контракты с ошибками - общее исключение, которое вы можете рассказать о подкислях.
Отметить интерфейс с помощью
[FaultContract( typeof( LogInFault ) )]
void LogIn( string userName, string password, bool auditLogin );
Затем, если есть исключение, вы можете сбросить эту конкретную ошибку:
throw new FaultException<LogInFault>( new LogInFault(), "message" );
Используйте сериализацию [DataContract]
по вашей ошибке - это избавит вас от необходимости обрабатывать все необходимые для сериализации исключения.
Ответ 2
Определенно избегайте бросать System.Exception для чего-либо другого, кроме кода throwaway.
Если аргумент метода недействителен, бросьте ArgumentException (или какое-то производное, более конкретное исключение). Проконсультируйтесь с документами для существующих исключений, прежде чем создавать свои собственные, но часто бывает полезно сделать это. (Вы можете получить свой собственный тип исключения из ArgumentException, конечно - если у вас есть определенный тип условия, которое вы хотите указать из нескольких мест, создание нового типа дает больше информации, чем просто помещать его в сообщение об ошибке. )
Теперь обработка ошибок в WCF может отличаться от обработки ошибок в "нормальной" структуре - я предлагаю вам обратиться к документам/книгам, определенным для WCF.
Ответ 3
Не стоит бросать System.Exception. Самая большая причина для этого - эффект, который он оказывает на вызывающий код. Как они должны обрабатывать исключение? Если вызывающий код будет обрабатывать исключение, тогда они должны поймать каждое исключение, что, вероятно, не самое лучшее для них.
Если какое-либо обстоятельство не распространяется на одно из стандартных исключений, тогда вы должны создать новый объект Exception, если исключение - это то, что вызывающий код должен обрабатывать как особый случай.
Ответ 4
Исключение System.Exception должно использоваться только как базовый класс для Исключений, никогда не быть брошенным напрямую.
Framework предлагает уже много допустимых классов Exception, таких как ArgumentException, ArgumentNullException, InvalidOperationException, FormatException, OverflowException и т.д.
Вы говорите, что делаете материал ввода/вывода, поэтому хорошая идея - посмотреть на подобные операции в рамках (например, int.Parse) и выбросить те же исключения для подобных ошибок.
Или выведите собственный класс исключений из существующего класса исключений, если ни один из них не соответствует вашим потребностям.
Ответ 5
Если вы выбросите System.Exception, то вызывающий должен поймать System.Exception. Обе стороны этого нет-нет, так как это оставляет нам говорить пользователю "что не работает", а не что-то более полезное.
An ArgumentException полезно, если вызывающий передал недопустимый аргумент. Если ваша функция имеет параметр int, что вам нужно быть четным числом, тогда вы будете бросать и ArgumentException сообщать вызывающему, какой параметр был недействительным и почему. Однако, если все аргументы были действительными, но проблема все еще существует, вам, вероятно, потребуется специальное исключение. Таким образом, вызывающий может с уверенностью сказать пользователю, что пошло не так.
Тест для меня действительно на стороне вызова. Если бы у меня было дюжина уловов, которые все сделали то же самое, тогда мне действительно нужно было только одно исключение. Однако, если бы у меня был один улов и у вас было бы выражение, сообщающее пользователю, что одна из трех вещей пошла не так, мне действительно нужны три уникальных исключения.
Ответ 6
Каковы руководящие принципы для того, когда создайте новый тип исключения вместо используя одно из встроенных исключений в .Net?
Если нет подходящего предопределенного класса исключений.
.NET FW очень богат, часто вы можете найти предопределенное исключение.
Если служба не может создать вывод, поскольку вход недействителен
Класс ArgumentException (система)
Исключение, которое бросается, когда один аргументов, предоставляемых методу недействительна.
Ответ 7
Всегда создавайте новый тип исключения (или используйте стандартный тип, если он вам подходит).
В этом случае вы можете обрабатывать исключения как группы.
Ответ 8
Как уже отмечали предыдущие плакаты, вы не должны бросать System.Exception. На самом деле, если вы запустили FxCop на свой код, это означало бы, что, как правило, нарушение.
Я рекомендую ознакомиться с главой 18 прикладного программирования .NET Framework или с главой 19 более поздней CLR через С# (2-е издание) для подробного руководства. Рихтер делает отличную работу по исправлению ошибочных представлений, которые многие разработчики придерживаются исключений.
В обеих книгах содержится список исключений, определенных библиотекой классов Framework. Посмотрите на список и выясните наиболее специфические исключения, которые может вызвать ваш код. Если вы можете восстановиться из исключения, сделайте это в этом блоке catch. Если вам нужно несколько блоков блокировки, организуйте их от наиболее специфических до наименее специфичных. Создайте настраиваемое исключение, если вы не можете найти его в существующем списке, который подходит для этой ситуации.