Есть ли какая-либо причина для создания исключения DivideByZeroException? - PullRequest
21 голосов
/ 08 апреля 2010

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

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

Например:

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

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

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

ПРИМЕЧАНИЕ: Я не говорю о перехвате этих ошибок, но конкретно о том, чтобы знать, есть ли когда-нибудь веские причины для их выброса.

ПРОСТО ПОВТОРЯТЬ :

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

Ответы [ 16 ]

20 голосов
/ 08 апреля 2010

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

12 голосов
/ 08 апреля 2010

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

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

5 голосов
/ 08 апреля 2010

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

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

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

4 голосов
/ 08 апреля 2010

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

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

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

3 голосов
/ 08 апреля 2010

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

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

2 голосов
/ 08 апреля 2010

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

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

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

ИЗМЕНЕНО В ДОБАВИТЬ:

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

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

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

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

Debug.Assert(dispenser != null);

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

1 голос
/ 08 апреля 2010

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

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

1 голос
/ 08 апреля 2010

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

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

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

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

1 голос
/ 08 апреля 2010

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

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

Кшиштоф Квалина, Проектирование многоразовых каркасов

0 голосов
/ 08 апреля 2010

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

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

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

...