Есть ли причина, чтобы бросить DivideByZeroException?

бывали ли случаи, когда это хорошая идея throw ошибки, которых можно избежать?

Я думаю конкретно о DivideByZeroException и ArgumentNullException

например:

double numerator = 10;
double denominator = getDenominator();

if( denominator == 0 ){
   throw new DivideByZeroException("You can't divide by Zero!");
}

есть ли какие-либо причины для создания такой ошибки?

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

ПРОСТО Повторяю!--15-->:

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

16 ответов


предположим, вы пишете библиотеку для работы с действительно большими целыми числами, которые не вписываются в Int64, тогда вы можете захотеть бросить DivideByZeroException для алгоритма деления, который вы пишете.


среда выполнения .NET уже очень хорошо бросает эти исключения. Они также очень описательны о том, что не так, вы не можете добавить хороший комментарий к сообщению об исключении. "Нельзя делить на ноль" не добавляет значения.

однако вы можете избежать многих из этих исключений, экранируя значения, переданные клиентским кодом. Вам понадобится ArgumentNullException с именем аргумента, если клиентский код передал null, ArgumentException когда он передал что-то, что ответственность DivideByZero поездки.


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

Если вы пишете библиотеку математики и имеете функцию Divide(int a, int b) Это делит их, если кто-то еще хочет использовать ваш метод и проходит в нуле, вы захотите создать исключение, чтобы они, как разработчик, знали, что они облажались вверх.

Если вы не создадите исключение, вы введете ошибки в свой код. Если я использовал ваш метод деления и ввел значения 10 и 0, что дает 10/0 и, следовательно, исключение, единственный правильный ответ-ошибка. Если вы решите изменить значения так, чтобы не возникало ошибок, или вернуть 0, это не то, что я ожидаю - я предполагаю, что мое разделение работало отлично, и никогда не замечаю проблемы. Я мог бы взять этот 0 и уйти и использовать его в других вычислениях, не зная, что это неправильно ответ, ведь 10/0 не 0.


вы должны использовать исключения для обработки исключительных случаев.

в этом случае, похоже, что ноль будет недопустимым пользовательским вводом. Вы должны проверить недопустимый пользовательский ввод и обработать его соответствующим образом до Вы дойдете до того, что исключение будет approriate.

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


Если вы говорите о коде, который непосредственно взаимодействует с пользовательским интерфейсом, то нет. Не знаю, почему ты этого хочешь.

однако, если вы создаете класс / объект, используемый другими devlopers, и они передали данные, которые явно глупы, то бросьте соответствующую ошибку во время проверки.


если вы пишете библиотеку BigInteger, то вы абсолютно должны бросить соответствующий DivideByZero исключения. Если ты пишешь библиотеку для покупок, то да...наверное, нет.

Я не могу в данный момент придумать хорошую причину, чтобы бросить NullReferenceException. Если вы создаете API с документацией, в которой говорится: "первый параметр HummingBirdFeeder.OpenSugarWaterDispenser(Dispenser dispenser, int flowRate) - Это сахара-вода, которую вы хотите открыть."И если кто-то затем приходит и передает нулевое значение этому методу, то вы должны определенно бросьте ArgumentNullException.

позволил NullReferenceException из вашего API будет просто расплывчатость, хотя, потому что это неправильно, и он протекает некоторые из ваших внутренних органов.

ОТРЕДАКТИРОВАНО, ЧТОБЫ ДОБАВИТЬ:

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

  • вы пишете публичный метод.
  • получаю значение null для аргумент в некотором смысле неуместен (т. е. метод не имеет смысла без этого конкретного аргумента).
  • документация для метода указывает, что значения null не допускаются.

в этом случае самое первое, что должен сделать ваш метод, это проверить значение null и выдать исключение, если условие нарушено.

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

Debug.Assert(dispenser != null);

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


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

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

Krzysztof Cwalina, Проектирование Многоразовых Фреймворков


слегка вводящий в заблуждение заголовок здесь, речь идет не о бросании (специального) DivideByZeroException, а о вопросе:

должен ли я использовать исключения при проверке пользовательского ввода?

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

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


Если вы писали числовой класс какой-либо формы и могли ожидать, что код, вызывающий ваш класс, выполнил проверку, то я вижу, что может быть полезно бросить DivisionByZeroException, но почти в любом другом случае было бы лучше проверить перед операцией и бросить и ArgumentException или ArgumentOutOfRange исключение по мере необходимости.

NullReferenceException является одним из зарезервированных исключений, которые использует платформа, которую вы никогда не должны перебрасывать открытый API, наряду с IndexOutOfRange, AccessViolationException и OutOfMemoryException. См. руководство по разработке рамок или код анализа предупреждение объяснение


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

по крайней мере, это то, что мой старший Дев сказал мне, когда я пытался поймать DivideByZeroException много лун назад.


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


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

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


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


считайте, что для двойников деление на ноль фактически приведет к значению: double.Бесконечность, двойная.Отрицательный или двойной.NaN, в зависимости от того, является ли числитель положительным, отрицательным или нулевым соответственно.

возможно, эти значения уже подходят для вашего случая, если нет, вы, вероятно, захотите проверить ввод и действовать соответственно, прежде чем выполнять разделение.

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


Если вы полагаетесь на фреймворк для выполнения работы (.NET или иначе), то вы должны пусть фреймворк выдает исключение.

Это облегчит потребителям ваших методов обработку исключений, которые генерируются стандартным способом.

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


выбрасывание исключения-дорогостоящая вещь с точки зрения ресурсов. Вы уже предотвратили появление исключения, так зачем его бросать? Если вам нужно сообщить пользователю, используйте некоторый механизм обмена сообщениями. Если вы хотите узнать об этом сами, запишите в журнал.