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

Оказывается, проблема была не в компиляции статической библиотеки, а в компоновке указанной библиотеки.

Проблема была исправлена ​​для меня путем изменения:

# Link executable
$(EXEC): $(OBJS)
    $(CC) $^ -o $(OUTDIR)$@ $(LDFLAGS) $(LIB)

На:

# Link executable
$(EXEC): $(OBJS)
    $(CC) $^ -o $(OUTDIR)$@ $(LIB) $(LDFLAGS)

Так, что статическая библиотека, которая является просто набором объектов, связана с другие объекты, прежде чем ссылаться на библиотеки CUDA в $ (LDFLAGS).

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

157
задан Even Mien 21 April 2009 в 20:31
поделиться

7 ответов

Мне нравится использовать: ArgumentException , ArgumentNullException и ArgumentOutOfRangeException .

  • ArgumentException - что-то есть неправильно с аргументом.
  • ArgumentNullException - Аргумент нулевой.
  • ArgumentOutOfRangeException - Я не часто его использую, но обычно используется индексация в коллекции и предоставление индекса, который к большому.

Существуют и другие опции, которые не столько фокусируются на самом аргументе, сколько оценивают вызов в целом:

  • InvalidOperationException - Аргумент может быть в порядке, но не в текущее состояние объекта. Кредит переходит в STW (ранее Yoooder). Проголосуйте и за его ответ .
  • NotSupportedException - Переданные аргументы действительны, но просто не поддерживается в этой реализации. Представьте себе FTP-клиента, и вы передаете команду, которую клиент не поддерживает.

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

Мне нравится, когда сообщения об ошибках указывают на помощь, документацию или другие ресурсы. Например, Microsoft сделала хороший первый шаг со своими статьями базы знаний, например, «Почему я получаю сообщение об ошибке« Операция прервана »при посещении веб-страницы в Internet Explorer?» . Когда вы сталкиваетесь с ошибкой, они указывают на статью базы знаний в сообщении об ошибке. Что они не делают хорошо, так это то, что они не говорят вам, почему конкретно это не удалось.

Спасибо еще раз STW (бывший Yoooder) за комментарии.


В ответ на ваше продолжение я бы сгенерировал ArgumentOutOfRangeException . Посмотрите, что MSDN говорит об этом исключении: выброшено

ArgumentOutOfRangeException когда метод вызывается и по крайней мере один из аргументов, переданных метод не является нулевым ссылка ( Ничего в Visual Basic) и не содержит действительного значения.

Таким образом, в этом случае вы передаете значение, но это не является допустимым значением, поскольку ваш диапазон составляет 1–12. Однако то, как вы документируете, проясняет, что выдает ваш API. Потому что хотя я мог бы сказать ArgumentOutOfRangeException , другой разработчик может сказать ArgumentException . Упростите и запишите поведение.

241
ответ дан 23 November 2019 в 21:44
поделиться

Я проголосовал за ответ Джоша , но хотел бы добавить еще один в список:

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

Update Взято из MSDN:

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

Допустим, у вашего объекта есть метод PerformAction (действие enmSomeAction), допустимыми являются enmSomeActions Open и Close. Если вы вызываете PerformAction (enmSomeAction.Open) два раза подряд, то второй вызов должен вызвать исключение InvalidOperationException (поскольку arugment был действителен, но не для текущего состояния элемента управления)

, поскольку вы уже делаете правильные вещи при программировании для защиты я должен упомянуть еще одно исключение - ObjectDisposedException. Если ваш объект реализует IDisposable, тогда у вас всегда должна быть переменная класса, отслеживающая состояние удаления; если ваш объект был удален и для него вызван метод, вы должны вызвать исключение ObjectDisposedException:

public void SomeMethod()
{
    If (m_Disposed) {
          throw new ObjectDisposedException("Object has been disposed")
     }
    // ... Normal execution code
}

Обновление: Чтобы ответить на ваши последующие действия: Это немного двусмысленная ситуация, и усложняется общим (не в смысле .NET Generics) типом данных, используемым для представления определенного набора данных; перечисление или другой строго типизированный объект были бы более идеальным соответствием - но у нас не всегда есть этот элемент управления.

Я лично склонялся бы к ArgumentOutOfRangeException и предоставил бы сообщение, которое указывает, что допустимые значения 1-12. Я рассуждаю так: когда вы говорите о месяцах, предполагая, что все целочисленные представления месяцев действительны, то вы ожидаете значение в диапазоне 1-12. Если бы действовали только определенные месяцы (например, месяцы, в которых было 31 день), вы бы не имели дело с самим диапазоном, и я бы выдал обобщенное исключение ArgumentException, в котором указаны действительные значения, и я также задокументировал бы их в комментариях метода.

NET Generics смысле) тип данных, используемый для представления определенного набора данных; перечисление или другой строго типизированный объект были бы более идеальным соответствием - но у нас не всегда есть этот элемент управления.

Я лично склонялся бы к ArgumentOutOfRangeException и предоставил бы сообщение, которое указывает, что допустимые значения 1-12. Я рассуждаю так: когда вы говорите о месяцах, предполагая, что все целочисленные представления месяцев действительны, то вы ожидаете значение в диапазоне 1-12. Если бы действовали только определенные месяцы (например, месяцы, в которых было 31 день), вы бы не имели дело с самим диапазоном, и я бы выдал обобщенное исключение ArgumentException, в котором указаны действительные значения, и я также задокументировал бы их в комментариях метода.

NET Generics смысле) тип данных, используемый для представления определенного набора данных; перечисление или другой строго типизированный объект были бы более идеальным соответствием - но у нас не всегда есть этот элемент управления.

Я лично склонялся бы к ArgumentOutOfRangeException и предоставил бы сообщение, которое указывает, что допустимые значения 1-12. Я рассуждаю так: когда вы говорите о месяцах, предполагая, что все целочисленные представления месяцев действительны, то вы ожидаете значение в диапазоне 1-12. Если бы действовали только определенные месяцы (например, месяцы, в которых было 31 день), вы бы не имели дело с самим диапазоном, и я бы выдал обобщенное исключение ArgumentException, в котором указаны действительные значения, и я также задокументировал бы их в комментариях метода.

перечисление или другой строго типизированный объект были бы более идеальным соответствием - но у нас не всегда есть этот элемент управления.

Я лично склонялся бы к ArgumentOutOfRangeException и предоставил бы сообщение, которое указывает, что допустимые значения 1-12. Я рассуждаю так: когда вы говорите о месяцах, предполагая, что все целочисленные представления месяцев действительны, то вы ожидаете значение в диапазоне 1-12. Если бы действовали только определенные месяцы (например, месяцы, в которых было 31 день), вы бы не имели дело с самим диапазоном, и я бы выдал обобщенное исключение ArgumentException, в котором указаны действительные значения, и я также задокументировал бы их в комментариях метода.

перечисление или другой строго типизированный объект были бы более идеальным соответствием - но у нас не всегда есть этот элемент управления.

Я лично склонялся бы к ArgumentOutOfRangeException и предоставил бы сообщение, которое указывает, что допустимые значения 1-12. Я рассуждаю так: когда вы говорите о месяцах, предполагая, что все целочисленные представления месяцев действительны, то вы ожидаете значение в диапазоне 1-12. Если бы действовали только определенные месяцы (например, месяцы, в которых было 31 день), вы бы не имели дело с самим диапазоном, и я бы выдал обобщенное исключение ArgumentException, в котором указаны действительные значения, и я также задокументировал бы их в комментариях метода.

Я рассуждаю так: когда вы говорите о месяцах, предполагая, что все целочисленные представления месяцев действительны, то вы ожидаете значение в диапазоне 1-12. Если бы действовали только определенные месяцы (например, месяцы, в которых было 31 день), вы бы не имели дело с самим диапазоном, и я бы выдал обобщенное исключение ArgumentException, в котором указаны действительные значения, и я также задокументировал бы их в комментариях метода.

Я рассуждаю так: когда вы говорите о месяцах, предполагая, что все целочисленные представления месяцев действительны, то вы ожидаете значение в диапазоне 1-12. Если бы действовали только определенные месяцы (например, месяцы, в которых было 31 день), вы бы не имели дело с самим диапазоном, и я бы выдал обобщенное исключение ArgumentException, в котором указаны действительные значения, и я также задокументировал бы их в комментариях метода.

43
ответ дан 23 November 2019 в 21:44
поделиться

В зависимости от фактического значения и какое исключение подходит лучше всего:

Если это не достаточно точно, просто выведите свой собственный класс исключений из ArgumentException .

Ответ Yoooder меня просветил. Вход является недопустимым , если он недействителен в любое время, тогда как вход является неожиданным , если он недопустим для текущего состояния системы.

35
ответ дан 23 November 2019 в 21:44
поделиться

исключение аргумента.

  • System.ArgumentException
  • System.ArgumentNullException
  • System.ArgumentOutOfRangeException
4
ответ дан 23 November 2019 в 21:44
поделиться

ArgumentException :

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

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

3
ответ дан 23 November 2019 в 21:44
поделиться

Краткий ответ:
Ни

Более длинный ответ:
с использованием аргумента * Exception (за исключением библиотеки, которая является Продукт на его, например, компонент библиотеки) является запахом. Исключения предназначены для обработки исключительных ситуаций, а не ошибок и не недостатков пользователя (т. Е. Пользователя API).

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

  • утверждения не нужно проверять, пока бросай утверждения делай, а тестируй против ArgumentNullException выглядит смешно (попробуйте)
  • Утверждения лучше сообщают о предполагаемом использовании устройства и являются ближе к тому, чтобы быть исполняемым документация, чем поведение класса Технические характеристики.
  • Вы можете изменить поведение нарушения утверждения. Например, в отладочной компиляции окно сообщения в порядке, так что ваш QA сразу же поразит вас (вы также получите разрыв IDE на линии, где это происходит), в то время как в модульном тесте вы можете указать сбой утверждения как тестовый сбой

Вот как выглядит обработка пустых исключений (с сарказмом, очевидно):

try {
    library.Method(null);
}
catch (ArgumentNullException e) {
    // retry with real argument this time
    library.Method(realArgument);
}

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

Кстати: в этом конкретном случае вы могли бы использовать тип Month вместо int. C # терпит неудачу, когда дело доходит до безопасности типов (Aspect # rulez!), Но иногда вы можете предотвратить (или отловить во время компиляции) эти ошибки все вместе.

И да, MicroSoft ошибается в этом.

1
ответ дан 23 November 2019 в 21:44
поделиться

Существует стандартное ArgumentException, которое вы можете использовать, или вы можете создать подкласс и создать свой собственный. Существует несколько определенных классов ArgumentException:

http://msdn.microsoft.com/en-us/library/system.argumentexception (VS.71) .aspx

Какой из них работает лучше всего

0
ответ дан 23 November 2019 в 21:44
поделиться