Должен ли я использовать return/continue вместо if-else?
В C, С++ и С# при использовании условия внутри функции или оператора цикла можно как можно раньше использовать оператор continue или return и избавиться от ветки else инструкции if-else. Например:
while( loopCondition ) {
if( innerCondition ) {
//do some stuff
} else {
//do other stuff
}
}
становится
while( loopCondition ) {
if( innerCondition ) {
//do some stuff
continue;
}
//do other stuff
}
и
void function() {
if( condition ) {
//do some stuff
} else {
//do other stuff
}
}
становится
void function() {
if( condition ) {
//do some stuff
return;
}
//do other stuff
}
Вариант "после" может быть более читаемым, если ветки if-else длинны, потому что это изменение исключает отступы для ветки else.
Является ли такое использование return/continue хорошей идеей? Существуют ли какие-либо проблемы с обслуживанием или читабельностью?
Ответы
Ответ 1
Компилятор почти наверняка создаст тот же код. Даже если это не так, разница будет, вероятно, неактуальной. Следовательно, соответствующий аргумент, конечно же, как люди его прочтут.
Поэтому вопрос заключается в том, как подобны "//делают некоторые вещи" и "делают другие вещи". Если они концептуально похожи, используйте if/else. Если они концептуально отличаются, используйте continue/return.
Ответ 2
Мой личный подход к выбору одного заключается в том, что если тело части if
очень короткое (максимум 3 или 4 строки), имеет смысл использовать вариант return/continue
. Если тело длинное, сложнее отслеживать поток управления, поэтому я выбираю версию else
.
Как правило, этот подход ограничивает использование стиля return/continue
, чтобы пропустить некоторые данные и избежать дальнейшей обработки, а не обрабатывать это, используя один из следующих методов (который лучше подходит if/else
).
Ответ 3
Это зависит немного от того, как долго ветки. Использование return/continue, которое вы описываете, хорошо, если начальная проверка if
коротка, а тело длинное. Если части if
и else
длинны, я бы выделил их для разделения функций.
Я рекомендую читать Code Complete, он много обсуждает такие вещи.
Ответ 4
Код будет более читаемым, если сначала будут проверены критерии завершения. Я всегда предпочитаю, проверяя условия, для которых требуется перерыв или возврат, а не те, которые потребуют длительного выполнения кода.
Я предпочитаю:
if (termination condn)
return;
// code
// code
к
if (success condn)
{
// code
// code
}
else
return;
Это облегчает чтение и понимание кода.
Ответ 5
Ответ glib заключается в том, что все зависит.
Мое общее мнение состоит в том, что если condition
- редкий, защитный (например, проверка на нуль) или условие ошибки, то я склонен использовать return
или continue
Если это ожидаемый случай, я, как правило, использую ваш первый подход.
Обратите внимание, однако, что я сказал "склонность". Граница между этими условиями неопределенна и может меняться в зависимости от проекта и с кем я работаю.
Ответ 6
Я обычно предпочитаю
while( loopCondition ) {
if( innerCondition ) {
DoStuff();
} else {
DoOtherStuff();
}
}
continue может быть трудно следовать, если длина DoStuff прошла 1-2-строчный порог (и его довольно легко упустить намерение). Это похоже на хорошую возможность реорганизовать логику на некоторые более мелкие методы.
Ответ 7
Не жертвуйте удобочитаемостью для преждевременной оптимизации.
Например:
void function() {
if( condition ) {
//do some stuff
} else {
//do other stuff
}
}
в большинстве случаев двоичный эквивалент
void function() {
if( condition ) {
//do some stuff
return;
}
//do other stuff
}
(т.е. полученный код, вероятно, тот же).
Но читаемость первого намного лучше, потому что вы можете ясно видеть, что код будет либо X, либо Y.
Ответ 8
1) Ввод или проверка состояния объекта. Следующий код:
void function() {
if( condition ) {
//do some stuff
return;
}
//do other stuff
}
хорошо, когда условие является некоторым требованием для работы функции. Это этап проверки ввода или проверки состояния объекта. Затем он чувствует себя вправе немедленно использовать возврат к акценту, эта функция вообще не запускалась.
2) Многоступенчатая обработка. В то время как /continue хорош, когда петля выталкивает элементы из некоторой коллекции и обрабатывает их многоступенчато:
while(foo = bar.getNext()) {
if(foo.empty())
continue;
if(foo.alreadyProcessed())
continue;
// Can we take a shortcut?
if(foo.tryProcessThingsYourself())
continue;
int baz = foo.getBaz();
if(baz < 0) {
int qux = foo.getQux();
if(qux < 0) {
// Error - go to next element
continue;
}
}
// Finally -- do the actual processing
baz = baz * 2;
foo.setBaz(baz);
}
В примере показано, насколько естественно использовать продолжить в сценарии, когда выполняются серии многоступенчатой обработки, когда каждая обработка может быть прервана различными условиями в разных местах.
Примечание: плинтус опубликовал реальный пример, который следует за тем, что сказано в 2).
3) Общее правило. Я использую продолжить и возвращать, когда это соответствует тому факту, что что-то было прервано. Я использую else, когда else является частью фактической обработки.
Ответ 9
Одна из возможных проблем с обслуживанием заключается в том, что если функция имеет несколько возвратов, то при отладке сложнее зафиксировать точку останова или трассировку при возврате. Это редко бывает проблемой, но когда вы пропускаете точку возврата, это боль. Я не думаю, что это имеет большое значение для продолжения цикла, поскольку условие цикла и вершина цикла все еще уникальны.
Кроме того: что говорят все остальные. Сделайте то, что наиболее читаемо, что зависит от относительной длины, важности и вероятности "некоторых вещей" и "других вещей". Чем короче, более тривиальным и более маловероятным является случай, тем менее тревожным является то, что он имеет специальный поток управления.
Ответ 10
как говорили другие люди, используйте только return/continue, если что-то не так.
Лично я использую только продолжение, если можно писать на одной строке, например:
while( loopCondition ) {
if( innerCondition ) continue;
//do other stuff
}
Если это невозможно записать так, как только код не станет уродливым, тогда if/else.
Ответ 11
Для усмешек я сделал поиск по моей кодовой базе для "continue"; просто чтобы понять, где он используется. Мы используем, если 695 раз по 59 проектам в одном решении, примерно 1500 исходных файлов.
Основные способы, которыми я их использую, - это быстрый фильтр:
foreach (Frobozz bar in foo) {
if (QuickFilterExclude(bar))
continue;
// extensive processing
}
Восстановление из ожидаемого исключения:
foreach (Frobozz bar in foo) {
Baz result = new Baz(kDefaultConfiguration);
try {
Baz remoteResult = boo.GetConfiguration();
}
catch (RemoteConnectionException) {
continue;
}
result.Merge(remoteResult);
ReportResult(result);
}
И, наконец, в государственной технике.
Ответ 12
Обычно я использую метод if-return при выпрыгивании из метода или цикла, потому что ничего не поделаешь.
Если тело длиннее, потому что выполняется существенная работа, я предлагаю использовать if-else и, возможно, использовать #region, чтобы дать блокам разумное имя и легко их сместить для людей, чтобы изучить поток управления. Это или сделать отдельные методы:)
Ответ 13
В моем коде было следующее:
while(){
boolean intersect = doesIntersect(interval_1,interval_2);
if(!intersect){
array.add(interval_2);
if(// another condition){
// Do some thing here
}
continue;
}
// other stuff to do if intersect
}
Сбив с толку, следует ли использовать продолжить там или использовать else, но я решил, что внутреннее условие if может сделать другое недочитанное, поэтому я использовал continue.
Я думаю, что читаемость важна!