Это плохая практика - возвращаться из блока try catch finally?


128

Итак, сегодня утром я наткнулся на код, который выглядел так:

try
{
    x = SomeThingDangerous();
    return x;
}
catch (Exception ex)
{
    throw new DangerousException(ex);
}
finally
{
    CleanUpDangerousStuff();
}

Теперь этот код отлично компилируется и работает так, как должен, но кажется неправильным возвращаться из блока try, особенно если есть связанный файл finally.

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


13
Одним из преимуществ этого стиля является то, что вам не нужно объявлять xза пределами tryблока. Вы можете хранить его объявление рядом с его использованием.
Дэвид Р. Триббл

Ответы:


169

Нет, это неплохая практика. Размещение returnтам, где это имеет смысл, улучшает читабельность и ремонтопригодность, а также упрощает понимание кода. Вам не нужно беспокоиться о том, что finallyблок будет выполнен, если returnвстретится оператор.


19

Final будет выполнен несмотря ни на что, поэтому это не имеет значения.


9
Нет, на самом деле, это не просто отключение, есть некоторые исключения, называемые асинхронными исключениями, такие как StackOverflowException, ThreadAbortException и OutOfMemoryException, которые могут привести к тому, что блок finally не будет выполнен. Прочтите об ограниченных областях выполнения для обработки этих сценариев.
Mehrdad Afshari

Эта ссылка объясняет это: return Statement и try ... catch ... finally Statement
amit jha

14

Лично я бы избегал такого рода кодирования, так как мне не хочется видеть операторы return перед операторами finally.

Мой разум прост и обрабатывает вещи довольно линейно. Поэтому, когда я просматриваю код для сухого прогона, у меня будет тенденция думать, что, как только я смогу добраться до оператора return, все последующее не имеет значения, что, очевидно, в данном случае неверно (не то чтобы это повлияло на оператор return, но какие могут быть побочные эффекты).

Таким образом, я бы расположил код так, чтобы оператор return всегда появлялся после операторов finally.


9

Это может ответить на ваш вопрос

Что на самом деле происходит при попытке {return x; } наконец {x = null; } заявление?

Из прочтения этого вопроса кажется, что у вас может быть еще одна структура try catch в инструкции finally, если вы думаете, что она может вызвать исключение. Компилятор определит, когда вернуть значение.

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


хммм очень интересно. Это означает, что это безопасно, но означает ли это, что этого следует избегать?
lomaxx

3
Лично я считаю, что это затрудняет читаемость вашего кода, и одного этого было бы достаточно, чтобы заставить меня придумать какой-то другой способ структурировать код. Но на самом деле это просто личные предпочтения.
Спенсер Рупорт,

3
Я склонен согласиться с вашими личными предпочтениями :)
lomaxx

Думаю, отдача там, где она есть. Метод вернет значение, если не возникнет исключение; не имеет значения, возникает ли исключение в коде окончательной очистки.
Лоуренс Дол

Обратите внимание , что ограничение по возвращению из окончательно не присутствует в Java (но я думаю , что ограничение является хорошей один - престижность C #).
Лоуренс Дол

5

Функционально разницы нет.

Однако есть одна причина не делать этого. Более длинные методы с несколькими точками выхода часто труднее читать и анализировать. Но это возражение больше связано с операторами return, чем с блокировками catch и finally.


Я бы оспорил это, так как вы можете получить больше вложенности, что также затруднит чтение более высокой цикломатической сложности
matt_lethargic

3

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

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

Я думаю, что, если оператор return так аккуратно помещен в качестве последнего оператора, другие с меньшей вероятностью придут и поместят несколько операторов return в другие части метода.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.