Я читал совет по этому вопросу о том, как следует рассматривать исключение как можно ближе к месту его возникновения.
Моя дилемма в отношении лучшей практики заключается в том, следует ли использовать try / catch / finally для возврата перечисления (или типа int, представляющего значение, 0 для ошибки, 1 для подтверждения, 2 для предупреждения и т. Д., В зависимости от случая), чтобы ответ всегда в порядке, или нужно пропустить исключение, чтобы вызывающая часть справилась с ним?
Из того, что я могу собрать, это может отличаться в зависимости от случая, поэтому оригинальный совет кажется странным.
Например, в веб-сервисе вы всегда хотели бы вернуть состояние, конечно, поэтому любое исключение должно обрабатываться на месте, но, скажем, внутри функции, которая отправляет / получает некоторые данные через http, вы хотели бы, чтобы исключение (например, в случае 404), чтобы просто перейти к тому, кто его запустил. Если вы этого не сделаете, вам придется создать какой-то способ информировать вызывающую часть о качестве результата (ошибка: 404), а также о самом результате.
Хотя можно попробовать перехватить исключение 404 внутри вспомогательной функции, которая получает / публикует данные, не так ли? Только я использую smallint для обозначения состояний в программе (и, конечно, для их надлежащего документирования), а затем использую эту информацию для целей проверки работоспособности (все в порядке / обработка ошибок) снаружи?
Обновление: я ожидал фатального / не фатального исключения для основной классификации, но я не хотел включать это, чтобы не нанести ущерб ответам. Позвольте мне уточнить, о чем идет речь: обработка исключений, а не исключений. Каков желаемый эффект: обнаружите ошибку и попробуйте исправить ее. Если восстановление невозможно, предоставьте наиболее значимый отзыв.
Опять же, с примером http get / post, вопрос в том, должны ли вы предоставить новый объект, который описывает, что случилось с исходным абонентом? Если бы этот помощник находился в используемой вами библиотеке, вы ожидаете, что он предоставит вам код состояния для операции, или вы включите его в блок try-catch? Если вы разрабатываете его, вы бы предоставили код состояния или сгенерировали исключение и позволили верхнему уровню преобразовать его в код состояния / сообщение вместо этого?
Сводка: Как вы выбрали, если часть кода вместо создания исключения возвращает код состояния вместе с любыми результатами, которые он может дать?
источник
Ответы:
Исключения следует использовать для исключительных условий. Создание исключения - это в основном утверждение: «Я не могу обработать это условие здесь; может ли кто-нибудь, кто находится выше в стеке вызовов, поймать это для меня и обработать это?»
Возвращение значения может быть предпочтительным, если ясно, что вызывающая сторона примет это значение и сделает с ним что-то значимое. Это особенно верно, если генерирование исключения влияет на производительность, т. Е. Оно может происходить в узком цикле. Создание исключения занимает намного больше времени, чем возвращение значения (как минимум на два порядка).
Исключения никогда не должны использоваться для реализации программной логики. Другими словами, не бросайте исключение, чтобы что-то сделать; бросить исключение, чтобы заявить, что это не может быть сделано.
источник
Несколько полезных советов, которые я однажды прочитал, заключались в том, чтобы создавать исключения, когда вы не можете прогрессировать, учитывая состояние данных, с которыми вы работаете, однако, если у вас есть метод, который может генерировать исключение, также предоставьте, где это возможно, метод для подтверждения того, являются ли данные на самом деле действителен до вызова метода.
Например, System.IO.File.OpenRead () вызовет исключение FileNotFoundException, если предоставленный файл не существует, однако он также предоставляет метод .Exists (), который возвращает логическое значение, указывающее, присутствует ли файл, который следует вызвать перед вызов OpenRead (), чтобы избежать любых неожиданных исключений.
Чтобы ответить на часть вопроса «когда я должен иметь дело с исключением», я бы сказал, где вы действительно можете что-то с этим сделать. Если ваш метод не может обработать исключение, вызванное вызываемым им методом, не перехватывайте его. Пусть он поднимется выше по цепочке вызовов к чему-то, что может с этим справиться. В некоторых случаях это может быть просто регистратор, слушающий исключение Application.UnhandledException.
источник
Это ужасный дизайн. Не «маскируйте» исключение, переводя его в числовой код. Оставьте это как правильное, однозначное исключение.
Вот для чего и исключения.
Это не универсальная правда вообще. Иногда это хорошая идея. В других случаях это не так полезно.
источник
if
операторам вместо (иногда) более простой обработки исключений. Ответ («Как выбрать ...») прост. Не . Я думаю, сказав это добавляет к разговору. Вы можете игнорировать этот ответ, однако.Я согласен с С. Лоттом . Поймать исключение как можно ближе к источнику может быть хорошей или плохой идеей в зависимости от ситуации. Ключ к обработке исключений состоит в том, чтобы ловить их только тогда, когда вы можете что-то с этим сделать. Поймать их и вернуть числовое значение вызывающей функции, как правило, плохо. Вы просто хотите позволить им всплыть, пока вы не сможете прийти в себя.
Я всегда рассматриваю обработку исключений как шаг от логики своего приложения. Я спрашиваю себя: если выброшено это исключение, как далеко я должен выполнить обход стека вызовов, прежде чем мое приложение будет в состоянии восстановления? Во многих случаях, если я ничего не могу сделать в приложении для восстановления, это может означать, что я не перехватываю его до верхнего уровня и просто регистрирую исключение, не выполняю работу и пытаюсь корректно завершить работу.
На самом деле не существует жесткого и быстрого правила, когда и как настроить обработку исключений, кроме как оставить их в покое, пока вы не узнаете, что с ними делать.
источник
Исключением являются красивые вещи. Они позволяют составить четкое описание проблемы времени выполнения, не прибегая к ненужной двусмысленности. Исключения могут быть напечатаны, подтипированы и могут обрабатываться по типу. Они могут быть переданы для обработки в другом месте, и если они не могут быть обработаны, они могут быть повторно подняты для обработки на более высоком уровне в вашем приложении. Они также автоматически вернутся из вашего метода, не вызывая много сумасшедшей логики для работы с запутанными кодами ошибок.
Вы должны бросить исключение сразу же после обнаружения недопустимых данных в вашем коде. Вы должны обернуть вызовы других методов в try..catch..finally для обработки любых исключений, которые могут быть сгенерированы, и если вы не знаете, как реагировать на любое данное исключение, вы бросаете его снова, чтобы указать более высоким уровням, что есть что-то не так, что должно быть обработано в другом месте.
Управление кодами ошибок может быть очень сложным. Вы обычно заканчиваете большим количеством ненужного дублирования в вашем коде и / или большим количеством грязной логики для обработки состояний ошибок. Быть пользователем и сталкиваться с кодом ошибки еще хуже, поскольку сам код не будет иметь смысла и не предоставит пользователю контекст для ошибки. С другой стороны, исключение может сказать пользователю что-то полезное, например: «Вы забыли ввести значение» или «Вы ввели недопустимое значение, вот допустимый диапазон, который вы можете использовать ...», или «Я не узнайте, что случилось, обратитесь в техподдержку, скажите, что я только что рухнул, и дайте им следующую трассировку стека ... ".
Итак, мой вопрос к ОП заключается в том, почему вы НЕ хотите использовать исключения при возврате кодов ошибок?
источник
Все хорошие ответы. Я также хотел бы добавить, что возврат кода ошибки вместо выдачи исключения может усложнить код вызывающей стороны. Скажем, метод A вызывает метод B, вызывает метод C, и C сталкивается с ошибкой. Если C возвращает код ошибки, теперь B должен иметь логику, чтобы определить, может ли он обработать этот код ошибки. Если это невозможно, то нужно вернуть его A. Если A не может обработать ошибку, что вы делаете? Бросить исключение? В этом примере код становится намного чище, если C просто выдает исключение, B не перехватывает исключение, поэтому он автоматически прерывается без какого-либо дополнительного кода, необходимого для этого, и A может перехватывать определенные типы исключений, позволяя другим продолжать вызов стек.
Это напоминает хорошее правило:
источник
Я использовал комбинацию обоих решений: для каждой функции проверки я передаю запись, которую я заполняю статусом проверки (код ошибки). В конце функции, если существует ошибка проверки, я выкидываю исключение, таким образом, я не выкидываю исключение для каждого поля, а только один раз.
Я также воспользовался тем, что создание исключения остановит выполнение, потому что я не хочу, чтобы выполнение продолжалось, когда данные неверны.
Например
Если вы полагаетесь только на логическое значение, разработчик, использующий мою функцию, должен учесть следующее:
но он может забыть и только позвонить
Validate()
(я знаю, что он не должен, но, возможно, он мог).Итак, в приведенном выше коде я получил два преимущества:
источник
Здесь нет одного ответа - вроде как нет одного вида HttpException.
Имеет большой смысл, что базовые HTTP-библиотеки выдают исключение, когда получают ответ 4xx или 5xx; В прошлый раз, когда я смотрел на спецификации HTTP, это были ошибки.
Что касается того, чтобы выбросить это исключение - или обернуть его и перебросить - я думаю, что это действительно вопрос использования. Например, если вы пишете оболочку для сбора некоторых данных из API и предоставления их приложениям, вы можете решить, что семантически запрос на несуществующий ресурс, который возвращает HTTP 404, имеет больше смысла, чтобы перехватить это и вернуть null. С другой стороны, ошибка 406 (недопустимая) может стоить выдать ошибку, поскольку это означает, что что-то изменилось, и приложение должно аварийно завершить работу, гореть и кричать о помощи.
источник