Существует ли предопределенное исключение ThisIsABugException? - PullRequest
2 голосов
/ 09 февраля 2012

.NET Framework имеет множество предопределенных исключений.Например, если в мой метод передан неверный параметр, я должен увеличить ArgumentException (или ArgumentNullException, если параметр был null).Если вызывается метод, который является недопустимым для текущего состояния объекта, я должен вызвать InvalidOperationException.

. Есть ли какое-то предопределенное исключение для ", этот код никогда не должен быть достигнут "дело?Вот пример:

void myMethod() {
    int a;

    ... /* Some complex code that manipulates a. In the end, "a" can only be 1 or 2. */

    switch (a) {
        case 1: ...
        case 2: ...
        default:  // just an extra sanity check
            // Oops, we should never be here.
            // There's apparently some bug in the code above.
            throw new ThereIsABugInTheCodeException();
    }
}

Я не думаю, что создание собственного исключения для такого редкого случая оправдано.С другой стороны, просто бросать Exception также не рекомендуется .Я думаю, что какой-то AssertionFailedException будет уместным, но я не нашел ни одного в .net Framework.(Обратите внимание, что Trace.Assert не выдает исключение, поэтому это тоже не вариант.)


EDIT : Чтобы уточнить: a - этоНЕ аргумент.Позвольте мне перефразировать вопрос, чтобы сделать его более понятным: в середине метода я делаю проверку работоспособности (просто чтобы убедиться, что в этом нет необходимости, если код в начале метода правильный).Я обнаружил, что проверка работоспособности не удалась и хотел бы сделать исключение.Который я бросаю?Я не думаю, что ArgumentException является правильным ответом, поскольку ArgumentException должен быть выдан только в том случае, если вызывающая сторона метода сделала что-то не так .Это не тот случай, здесь.Сам метод понимает во время выполнения, что он содержит ошибку.

Ответы [ 6 ]

4 голосов
/ 09 февраля 2012

Как ни странно .NET Framework не содержит исключения для описания логических или внутренних ошибок. Но, с другой стороны, .NET Framework должен иметь уровень качества, при котором не должно быть необходимости создавать исключения для внутренних ошибок. Доверяете ли вы вызову .NET API, который в документации заявил, что он может выдать InternalErrorException? Помните, что исключения, полученные из SystemException, являются исключениями, используемыми платформой. Может быть полезно повторно использовать эти исключения, но исключения были созданы для использования платформой, а не вашей платформой / приложением.

Вы можете использовать ArgumentException, ArgumentNullException, ArgumentOufOfRangeException, NotSupportedException и InvalidOperationException в тех случаях, когда ваши методы вызываются неожиданным образом.

Вы также можете создать свой собственный InternalErrorException.

Microsoft предлагает более общее решение этой проблемы Кодовые контракты . Многие контракты могут быть проверены во время компиляции, помогая вам создавать лучший код, и вы можете использовать Contract.Assume и Contract.Assert для проверки условий в вашем коде. Программа перезаписи вставит код, который выдаст ContractException, если условие ложно. Это исключение было разработано особым образом (из документации по кодам контрактов DevLabs ):

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

3 голосов
/ 09 февраля 2012

Для случая, который вы показываете, я бы также использовал ArgumentException, возможно, ArgumentOutOfRangeException.

Редактировать Я не выглядел достаточно внимательно, и хотя switchбыл на аргумент метода, но, видимо, это не так.Так что ArgumentException, вероятно, не применимо.Остальная часть моего ответа остается неизменной.

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

Вероятно, вам следуетПодумайте об использовании Debug.Assert или Trace.Assert в этом случае, или сверните свой собственный обработчик, который по сути вызывает Environment.FailFast.

Является ли такое поведение правильным или приемлемым для вашего приложения - это решение, которое вы должны принять.

Обновление : Возможно, вы также захотите изучить Контракты кодов .Какой AFAIK, может быть адаптирован в их поведении во время выполнения, чтобы генерировать исключения, прерывать процесс или ничего не делать.

2 голосов
/ 09 февраля 2012

Я бы использовал ArgumentException в этом случае.

Вы получаете неожиданное значение для аргумента a.

throw new ArgumentException(string.Format("Unexpected value {0} for a.", a);

Хотя в зависимости от точного сценария ArgumentOutOfRangeException может быть более подходящим, как прокомментировал @ todda.speot.is.

1 голос
/ 09 февраля 2012

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

0 голосов
/ 09 февраля 2012

ThisIsABugException концептуально неверен, я бы сказал.

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

Поэтому, когда вы проверяете контракт метода (параметры), вы вызываете ArgumentException или его дочерние элементы.

Если в пределахваш метод вы называете чем-то ненадежным и получаете какой-то странный результат, тогда вы, вероятно, должны поднять что-то значимое, а не потерпеть неудачу с «о, баг! баг!».Ошибка действительно, и что?Я предпочел бы поднять что-то значимое в контексте операции.

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

Вот почему вы никогда не хотите вызывать ThisIsABugException или что-то в этом роде.похоже.

0 голосов
/ 09 февраля 2012

Вы уверены, что существует понятие "ошибка исключения"?

В вашем примере это определенно исключение ArgumentOutOfRangeException, если a является аргументом.

Если ваш код пытаетсявыполнить некоторый код, который никогда не должен выполняться , тогда я думаю, что нужно что-то более важное, чем " Эй! Ошибка! " upstream .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...