#c# #exception
#c# #исключение
Вопрос:
Я читал, что создание исключений — дорогостоящая операция. Однако разве создание собственных исключений не делает ваш код более выразительным и читаемым?
Некоторые из моих коллег предполагают, что вам следует просто использовать System.Создайте исключение и вставьте свой пользовательский текст в сообщение вместо создания нового пользовательского исключения.
Меня интересуют другие мнения. Ценю любые предложения.
Комментарии:
1. Ммм, как связаны создание исключений и определение ваших собственных классов исключений …? Используете ли вы
System.Exception
или производны от него или какого-либо другого встроенного класса, вам все равно придется его создавать, поэтому затраты на фактическую генерацию и выбрасывание исключений. Не пишу их.2. Ваш коллега морочит вам голову или — если нет — надеюсь, он не будет вашим коллегой намного дольше.
3. Если не… они имели в виду, что писать пользовательские классы, а затем создавать их, стоит больше человеко-минут, чем просто использовать встроенные с самого начала. В этом случае … смехотворно.
4. Насколько я могу судить, пользовательские исключения не продаются: http://shop.ebay.com /
Ответ №1:
Не выбрасывать System.Exception
. Никогда.
Проблема с этим заключается в вызывающем коде. Перехватывать общий Exception
объект — плохая практика по многим причинам. Если вы создаете экземпляр Exception
базового класса, то у вызывающего кода нет другого выбора, кроме как перехватывать Exception
, если они хотят это обработать. Это вынуждает вызывающий код использовать плохую практику.
Кроме того, вызывающий код не имеет надежных средств определения того, каким было исключение, если все, что он получает, это Exception
.
Обычно лучше всего использовать одно из заранее определенных исключений, если таковые имеются ( ArgumentException
, InvalidOperationException
и т.д.). Если ни одно из них не описывает ситуацию правильно, то пользовательский класс исключений — отличный вариант.
Комментарии:
1. В случаях, когда нет ничего разумного, что можно было бы сделать, кроме регистрации исключения, и нет подходящего исключения BCL под рукой (хотя это маловероятно), выбрасывание
Exception
лучше, чем создание бессмысленного пользовательского исключения.2. Просто из любопытства, вы когда-нибудь писали код для перехвата
ArgumentException
?3. @Джефф Стернал — В таком случае более уместно создать
ApplicationException
.4. @Jeffrey — Я не уверен, что это добавляет какую-либо ценность, подобно тому, как MS больше не предлагает извлекать пользовательские исключения из
ApplicationException
(«Первоначально считалось, что пользовательские исключения должны быть производными от класса ApplicationException; однако на практике не было обнаружено, что это добавляет значительную ценность. Для получения дополнительной информации см. Рекомендации по обработке исключений».)5. @Jeffrey L Whitledge: Поскольку единственная причина, которую вы приводите для того, чтобы не выбрасывать
Exception
, заключается в том, что люди могут перехватывать ваше исключение отдельно от других, тогда в чем преимущество выбрасыванияArgumentException
вместо этого? Я просто не чувствую, что приведенные здесь рассуждения заслуживают жесткого подхода, который вы защищаете. (Редактировать: я не говорю, что вы никогда не должны бросатьArgumentException
— я просто говорю, что, возможно, это немного перебор, чтобы никогда никогда не бросатьException
.)
Ответ №2:
Накладные расходы на выдачу самого исключения (создание объекта, перемещение по стеку и т.д.) Являются дорогостоящими. Создание собственного класса exception практически не добавляет накладных расходов, поэтому, если вы собираетесь создавать исключение, не создавайте его new Exception("message")
!
Ответ №3:
Исключения не предназначены для чтения людьми (хотя их сообщения и трассировки стека читаются людьми), они предназначены для чтения кодом. Если есть что-то, что ваш код может сделать в ответ на пользовательское исключение, непременно сделайте это. Но исключение просто предназначено для регистрации, нет смысла создавать пользовательское.
Накладные расходы на пользовательские исключения заключаются в том, что их еще нужно поддерживать и тестировать. Если существующее исключение подходит, используйте его вместо этого. (Например, ArgumentNullException
вместо ZipCodeNullException
.)
Ответ №4:
- Если есть какая-либо причина для того, чтобы ваше исключение было перехвачено и обработано иначе, чем стандартные исключения, тогда вам следует создать свой собственный класс.
- Если есть какая-либо причина, по которой ваше исключение принимает другие аргументы (например, для создания сообщения специального формата на основе набора аргументов, которые у вас часто бывают), тогда вам следует создать свой собственный класс.
В любом другом случае вы в безопасности, просто используя Exception
. Вообще говоря, создание экземпляра или выдача пользовательского исключения на самом деле обходится не дороже, чем стандартное исключение, по крайней мере, не по сравнению с затратами на выдачу исключения в первую очередь. Исключения, по определению, должны быть исключительными, и поэтому производительность во время генерирования исключения не является проблемой. Суть в том, чтобы иметь всю необходимую информацию, когда придет время разобраться, почему было сгенерировано это исключение.
Ответ №5:
Вы никогда не должны бросать System.Exception
, потому что тогда единственный способ перехватить is — это by catch(System.Exception)
. Перехватывать такое общее исключение — очень плохая практика. Вы должны перехватывать конкретные исключения, которые дают вам возможность правильно обрабатывать их без сбоев программного обеспечения. Создавая пользовательские исключения, вы даете себе возможность потенциально распознавать их и восстанавливаться после них.
Например, если ваш код предназначен для открытия файла, и вы получаете неизвестное исключение, как вы восстанавливаетесь после него? Однако, если вы обнаружите исключение из определенного файла, которое не найдено, восстановить его будет намного проще. Вы можете определенно сообщить пользователю, что файл не существует.
Я не вижу оснований полагать, что пользовательские исключения стоят дороже, чем встроенные.
Ответ №6:
«Дорогой» — термин относительный, и, как уже следует из названия, исключение должно быть исключением, поэтому оно, вероятно, не повлияет на производительность вашего кода. Стоимость создания исключения, насколько я знаю, не зависит от типа исключения, поэтому вам не следует ограничивать себя системой.Исключение.
Но самое важное:http://c2.com/cgi/wiki ?Преждевременная оптимизация
Ответ №7:
Я предпочитаю использовать наиболее подходящее встроенное исключение, и если оно еще не существует, извлекаю свое собственное из System.Исключение ApplicationException.
Я бы не рекомендовал использовать System.Исключение с пользовательским сообщением.
Ответ №8:
Ваш коллега несет чушь. Создание исключения обходится одинаково независимо от класса.
И, честно говоря, все эти разговоры о «дорогих» исключениях — да, они дороже, чем проверка на нуль или что-то подобное, поэтому никогда не используйте их в качестве замены какой-либо проверки работоспособности, но их следует поощрять там, где они имеют смысл (например, IOException, это отличный вариант использования для них — проблемы с вводом-выводом являются исключительным случаем, и они обычно должны обрабатываться вне обычного потока программы).
Комментарии:
1. Создание экземпляра исключения не является особенно дорогостоящим; его выдача является.
2. Это не более затратно, независимо от того, является это пользовательским или нет — операция throw не зависит от типа.