Возврат исключений - PullRequest
       2

Возврат исключений

0 голосов
/ 28 апреля 2018

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

Exception f()
{
    try
    {
        // Do something.
        return null;
    }
    catch(Exception e)
    {
        return e;
    }
}

Я знаю, что это считается плохой практикой, но есть ли какие-либо технические причины, чтобы этого избежать?

РЕДАКТИРОВАТЬ: Это не тот же вопрос, что и Это плохая практика возвращать исключения из ваших методов . Я спрашиваю о технических причинах, а не о лучших практиках.

Ответы [ 2 ]

0 голосов
/ 28 апреля 2018

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

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

Во-вторых, Exception тяжелее, чем какое-то перечисление статуса, чтобы указать, какой тип ошибки произошел. Трудно понять, какую выгоду вы получаете от объекта ответа типа исключение. Предположительно, требуется, чтобы вызывающий абонент впоследствии выполнил набор if (response is FileNotFoundException) .... и решил, что он хочет сделать для каждого.

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

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

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

Exception error;
error = GetData(out data);
if (error is DbException) return error;
if (error is ArgumentOutOfRangeException) return error;
// if (error is ....... etc
error = ApplyChangesToData(data);
// if (error is ....... etc
error = SaveData(data);
// if (error is ....... etc

Теперь ставки высоки, если я что-то пропустил, потому что мой частично созданный объект данных может затем пройти через метод ApplyChangesToData и затем сохраниться обратно в базу данных в поврежденной форме. Это может быть так просто, как вы не ожидаете, что внутренне GetData попадет в SocketException или OutOfMemoryException. Это не просто делает вашу абстракцию утечкой, это означает, что, если у вас нет утечки абстракции, ваш код не может быть безопасно написан. Мой код должен знать, говорите ли вы с SqlServer, Oracle, Mongo или чем-то еще, чтобы я мог предвидеть все возможные исключения, которые вы можете перенастроить, и включить их в мои строки if. Конечно, я мог бы добавить другое и бросить любой объект исключения, но, вероятно, вы не хотите этого делать, иначе вы бы его не поймали.

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

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

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

0 голосов
/ 28 апреля 2018

Нет никаких «технических» причин, чтобы этого избежать. То есть .Net Framework с удовольствием поддержит этот тип соглашения.

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

Можно также создать исключение, не выбрасывая его:

Exception f()
{
    return new Exception("message");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...