делать {…} в то время как (ложь)

125

Я смотрел код человека и заметил, что у него, похоже, есть шаблон в своих функциях:

<return-type> function(<params>)
{
 <initialization>

 do
 {
   <main code for function>
 }
 while(false);

 <tidy-up & return>
}

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

Мистер мальчик
источник
2
Вы пробовали изменить его на «нормальную» версию и посмотреть, компилируется ли она? Если он не может скомпилироваться при обычной записи, ошибка компилятора может дать ключ к пониманию того, почему это было сделано.
Марк Байерс,
11
Почему бы не спросить «индивидуума», а не спрашивать нас о его намерениях?
1
Возможно, его профессор потребовал, чтобы он использовал a, do...while()и с тех пор он использовал этот код в качестве шаблона функции.
Hogan
6
@Neil ... Я не хочу выглядеть глупо, когда я противостою ему, и он объясняет сверхсовременное использование C ++, о котором я никогда не думал.
Мистер Бой
6
Кажется, уже есть довольно много разных ответов, можете ли вы спросить исходного автора, каковы были их намерения, и опубликовать ответ?
nevets1219

Ответы:

175

Вы можете breakвыйти из do{...}while(false).

Томас Эдинг
источник
95
+1, потому что, вероятно, это и есть намерение кода, но выполнение чего-то подобного - просто идиотски замаскированный goto. Если вы считаете, что goto - правильный инструмент для работы, тогда вам следует просто использовать # $ (* # @ goto.
dsimcha
56
Это больше, чем замаскированный goto. Это ограниченный (структурированный) goto.
Томас Эдинг
19
Каким образом это «ограничено»? Только прыжки вперед вряд ли являются «ограничением». Goto - это goto, и нарядить его так, чтобы он выглядел так, как будто он не один, хуже, чем просто использовать goto.
Аноним.
45
@Anon .: Прыжок вперед - это ограничение для goto, а прыжок - определенно ограничение. Настоящая проблема с gotos - это спагетти-код, и переход вперед и назад сильно ограничивает его.
Дэвид Торнли,
33
Фактический цикл семантически не является переходом. Условное выражение семантически не является goto. «Переход к концу функции и сделать очищающий код» является семантический Гото. Используйте gotos, когда применяется семантика, не приукрашивайте что-то семантически иное, потому что вы их боитесь.
Аноним.
126

Многие люди отмечают, что это часто используется с break как неудобным способом написания «goto». Вероятно, это правда, если это написано прямо в функции.

В макросе OTOH do { something; } while (false)- это удобный способ ПРИНУДИТЕЛЬНО поставить точку с запятой после вызова макроса, за которым не может следовать никакой другой токен.

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

Бен Фойгт
источник
18
+1 за упоминание о полезности этого в макросах; Я удивлен, что никто об этом не упомянул!
Ник Мейер,
7
Да, макросы на самом деле вполне допустимое использование this. Конечно, вне макросов это просто глупо ...;)
jalf
12
Это не неудобно, это полезно, потому что это goto с ограничением - это означает, что любые переменные, которые вы объявляете в цикле do, уничтожаются, тогда как goto этого не делает.
Ана Беттс,
9
@Paul: Ничто не мешает вам добавить фигурные скобки вокруг кучи операторов, чтобы заставить такое поведение с помощью goto.
erikkallen
5
@Paul: goto out из блока определенно вызывает уничтожение локальных переменных в C ++, как и break. А в C переменные на самом деле не уничтожаются, их пространство стека просто восстанавливается.
Бен Фойгт,
25

Разрыв как goto, вероятно, является ответом, но я предложу еще одну идею.

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

Помните, что хотя последний C ++ позволяет {...}делать что угодно, это было не всегда.

Hogan
источник
30
В этом случае он мог бы просто использовать фигурные скобки.
Неманья Трифунович
2
@Nemanja, вы были бы удивлены, узнав, сколько разработчиков этого не знают и попробуют что-то связанное с тем, что предлагает Хоган
Polaris878,
8
@Polaris @Nemanja, я понял, что вы можете создать новую локальную область видимости {} где угодно , только когда я программировал на C / C ++ около 4 лет .. Это особенно удобно в switch-caseкоде
Earlz
1
@Nemanja: Я не знаю точно, когда, но я уверен, что {...}это более современная разработка на C ++ (помните, что первый C ++, который я использовал, был реализован с помощью препроцессора и не позволял это современное использование). автор был просто олдскулом.
Hogan
2
Когда это не позволяло устанавливать брекеты повсюду? Я начал программировать около 15 лет назад, и тогда это было разрешено (как в моем учебнике, так и во всех компиляторах, которые я пробовал).
erikkallen
20

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

Это может сделать утомительное дерево if / else-if намного более легким для чтения, просто имея необходимость прерывать работу всякий раз, когда достигается точка выхода, а остальная часть логики встроена впоследствии.

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

Cameron
источник
15
Тогда просто используйте честный, простой goto вместо тонко замаскированного goto.
dsimcha
4
Мне так больше нравится. Его легко читать, и он не несет на себе клейма goto.
Кэмерон
8
gotos очень легко читать, если использовать их экономно и локально. Они получили свое клеймо со времен, когда они были основной формой контроля потока и перепрыгивали через сотни строк.
dsimcha
13
Отказ от использования goto из-за «стигмы» - верный признак программирования культа карго.
Аноним.
6
Не говоря уже о том, что масса кода очистки - дурной запах. Это C ++, поэтому код очистки обычно должен находиться в деструкторах, вызываемых во время обработки RAII.
Дэвид Торнли,
12

Я видел такой код, поэтому вы можете использовать его breakкак своего gotoрода.

Брайан Янг
источник
10

Это просто извращение, whileчтобы получить семантику goto tidy-upбез использования слова goto.

Это плохая форма , потому что , когда вы используете другие петли внутри внешний становятся неоднозначными для читателя. «Это должно идти к выходу? Или это предназначено только для выхода из внутреннего цикла?»whilebreaks

Джон Кнеллер
источник
10

Думаю, удобнее писать breakвместоgoto end . Вам даже не нужно придумывать название для ярлыка, чтобы прояснить намерение: вы не хотите переходить к ярлыку с определенным именем. Вы хотите уйти отсюда.

Также есть вероятность, что скобки вам все равно понадобятся. Итак, это do{...}while(false);версия:

do {
   // code
   if (condition) break; // or continue
   // more code
} while(false);

И вот как вам нужно было бы это выразить, если бы вы хотели использовать goto:

{
   // code
   if (condition) goto end;
   // more code
}
end:

Я думаю, что смысл первой версии намного легче понять. Также легче писать, проще расширять, легче переводить на язык, который не поддерживает goto, и т. Д.


Наиболее часто упоминаемое беспокойство по поводу использования breakзаключается в том, что это плохо замаскировано goto. Но на самом деле breakимеет большее сходство с return: Обе инструкции выходят из блока кода, который в значительной степени структурирован по сравнению с goto. Тем не менее, обе инструкции допускают несколько точек выхода в блоке кода, что иногда может сбивать с толку. В конце концов, я бы попытался найти наиболее четкое решение, каким бы оно ни было в конкретной ситуации.

Роберт
источник
О, я только что заметил, что не полностью понял вопрос, прежде чем ответить. Я думал, что речь идет об использовании do{ ... }while(false);в целом. Но на самом деле речь идет об использовании его для имитации какой-то try{ ... }finally{ ... }.
Роберт
Хорошее наблюдение за параллелью между break и return, а не goto. Согласитесь, что самое ясное решение - лучшее. Во многих случаях, вероятно, проще инкапсулировать такой код в его собственную отдельную функцию, которая использует return, а не break, а затем выполняет очистку в вызывающей функции.
persiflage
7

Этот трюк используют программисты, которые слишком стесняются использовать явное выражение gotoв своем коде. Автор приведенного выше кода хотел иметь возможность сразу перейти к точке «очистить и вернуть» из середины кода. Но они не хотели использовать ярлык и явное goto. Вместо этого они могут использовать breakвнутреннюю часть вышеуказанного «фальшивого» цикла для достижения того же эффекта.

Муравей
источник
7

Это очень распространенная практика. В С . Я пытаюсь думать об этом так, как будто вы хотите солгать себе таким образом: «Я не использую goto». Если подумать, нет ничего плохого в том, чтобы gotoиспользовать аналогично. Фактически это также уменьшило бы уровень отступа.

Тем не менее, я заметил, что очень часто эти do..whileпетли имеют тенденцию к росту. И тогда они получают ifs иelse s внутри, делая код на самом деле не очень читаемым, не говоря уже о тестируемом.

Те , do..whileкак правило , предназначены , чтобы сделать очистку . Во что бы то ни стало, я бы предпочел использовать RAII и раньше возвращаться из короткой функции. С другой стороны, C не предоставляет столько удобства, как C ++ , что делает его do..whileодним из лучших подходов к очистке.

Дмитрий
источник
6

Похоже на программиста на C. В C ++ автоматические переменные имеют деструкторы, которые вы используете для очистки, поэтому не нужно ничего убирать перед возвратом. В C у вас не было этой идиомы RAII , поэтому, если у вас есть общий код очистки, вы либоgoto его, либо используете сквозной цикл, как указано выше.

Его главный недостаток по сравнению с идиомой C ++ заключается в том, что он не убирается, если в теле возникает исключение. В C не было исключений, так что это не было проблемой, но это стало плохой привычкой в ​​C ++.

Пит Киркхэм
источник
4

Несколько объяснений. Первый - общий, второй - специфичный для макросов препроцессора C с параметрами:

Управление потоком

Я видел, как это использовалось в простом коде C. По сути, это более безопасная версия goto, так как вы можете выйти из нее, и вся память будет очищена должным образом.

Почему что-то вроде gotoдолжно быть хорошим? Что ж, если у вас есть код, в котором практически каждая строка может возвращать ошибку, но вам нужно реагировать на все из них одинаково (например, передавая ошибку вызывающему абоненту после очистки), это обычно более читабельно, чтобы избежать if( error ) { /* cleanup and error string generation and return here */ }as это позволяет избежать дублирования кода очистки.

Однако в C ++ есть исключения + RAII именно для этой цели, поэтому я считаю это плохим стилем кодирования.

Проверка точки с запятой

Если вы забудете точку с запятой после вызова макроса, подобного функции, аргументы могут нежелательным образом сжиматься и компилироваться в допустимый синтаксис. Представьте себе макрос

#define PRINT_IF_DEBUGMODE_ON(msg) if( gDebugModeOn ) printf("foo");

Это случайно называется

if( foo )
    PRINT_IF_DEBUGMODE_ON("Hullo\n")
else
    doSomethingElse();

«Еще» будет считаться ассоциироваться с gDebugModeOn, так что, когда fooэтоfalse произойдет, произойдет полная противоположность того, что было задумано.

Предоставление области для временных переменных.

Поскольку do / while имеет фигурные скобки, временные переменные имеют четко определенную область видимости, из которой они не могут выйти.

Как избежать предупреждений о потенциально нежелательных точках с запятой

Некоторые макросы активируются только в отладочных сборках. Вы определяете их как:

#if DEBUG
#define DBG_PRINT_NUM(n) printf("%d\n",n);
#else
#define DBG_PRINT_NUM(n) 
#endif

Теперь, если вы используете это в сборке выпуска внутри условного оператора, он компилируется в

if( foo )
    ;

Многие компиляторы видят в этом то же, что и

if( foo );

Что часто пишется случайно. Итак, вы получите предупреждение. Do {} while (false) скрывает это от компилятора и принимается им как признак того, что вы действительно хотите здесь ничего делать.

Как избежать захвата строк условными операторами

Макрос из предыдущего примера:

if( foo )
    DBG_PRINT_NUM(42)
doSomething();

Теперь, в отладочной сборке, поскольку мы обычно включаем точку с запятой, это компилируется нормально. Однако в сборке релиза это внезапно превращается в:

if( foo )

doSomething();

Или более четко отформатированный

if( foo )
    doSomething();

Это совсем не то, что было задумано. Добавление do {...} while (false) вокруг макроса превращает отсутствующую точку с запятой в ошибку компиляции.

Что это значит для ОП?

В общем, вы хотите использовать исключения в C ++ для обработки ошибок и шаблоны вместо макросов. Однако в очень редких случаях, когда вам все еще нужны макросы (например, при генерации имен классов с помощью вставки токенов) или вы ограничены простым C, это полезный шаблон.

uliwitness
источник
Что касается объема, вам не нужен петлевой аппарат; «прикрас» блок является законным: x =1; y = 2; { int tmp = y; y = x; x = tmp; }.
chepner
Однако неукрашенный блок не требует наличия пропущенной точки с запятой, что может иметь нежелательные побочные эффекты. Делать пока(); ТРЕБУЕТСЯ точка с запятой и, таким образом, например, не приводит к втягиванию следующих операторов в «если», если макрос ничего не определяет в сборке выпуска, как в моем примере выше.
uliwitness
Разве этого нельзя избежать, просто предоставив более точное определение макросу? #define DBG_PRINT_NUM(n) {},
chepner 06
1
Нет, потому что {} - это полный оператор, т. Е. Эквивалентный ";". Итак, если вы напишете, if(a) DBG_PRINT_NUM(n); else other();он не будет компилироваться. Допустимо только if(a) {} else other();или if(a) ; else other();, но if(a) {}; else other();это не так, потому что это делает предложение «if» состоящим из двух операторов.
uliwitness 08
2

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

do {
    if (!condition1) break;
    some_code;
    if (!condition2) break;
    some_further_code;
    // …
} while(false);
гумбо
источник
7
Это похоже на попытку избежать употребления gotoтолько потому, что кто-то слышал, что это «плохо».
Аноним.
1
Возможно, но в C ++ есть исключения именно по этой причине.
TED
2

Я думаю, что это сделано для использования breakили continueоператоров. Какая-то логика кода "goto".

Иван Невоструев
источник
2

Все просто: очевидно, вы можете в любой момент выйти из ложного цикла, используя breakоператор. Кроме того, doблок - это отдельная область (что также может быть достигнуто с помощью{ ... } только с помощью).

В такой ситуации было бы лучше использовать RAII (объекты автоматически разрушаются правильно, когда функция завершается). Другой подобной конструкцией является использование goto- да, я знаю, что это зло , но с ее помощью можно получить общий код очистки, например:

<return-type> function(<params>)
{
 <initialization>

 <main code for function using "goto error;" if something goes wrong>

 <tidy-up in success case & return>

 error:

 <commmon tidy-up actions for error case & return error code or throw exception>
}

(В качестве отступления: конструкция do-while-false используется в Lua для поиска отсутствующего continueоператора.)

AndiDog
источник
2

Многие ответившие назвали причину do{(...)break;}while(false) . Хотелось бы дополнить картину еще одним примером из жизни.

В следующем коде мне пришлось установить перечислитель operationна основе адреса, на который указывает dataуказатель. Поскольку сначала switch-case может использоваться только для скалярных типов, я сделал это неэффективно.

if (data == &array[o1])
    operation = O1;
else if (data == &array[o2])
    operation = O2;
else if (data == &array[on])
    operation = ON;

Log("operation:",operation);

Но поскольку Log () и остальной код повторяются для любого выбранного значения операции, я блуждал, как пропустить остальные сравнения, когда адрес уже обнаружен. А вот здесь и do{(...)break;}while(false)пригодится.

do {
    if (data == &array[o1]) {
        operation = O1;
        break;
    }
    if (data == &array[o2]) {
        operation = O2;
        break;
    }
    if (data == &array[on]) {
        operation = ON;
        break;
    }
} while (false);

Log("operation:",operation);

Можно задаться вопросом, почему он не мог сделать то же самое breakв ifзаявлении вроде:

if (data == &array[o1])
{
    operation = O1;
    break;
}
else if (...)

breakвзаимодействует только с ближайшим заключающего цикла или переключателя, будь то for, whileили do .. whileтип, поэтому , к сожалению , что не будет работать.

4pie0
источник
1

Сколько лет было автору?

Я спрашиваю, потому что однажды в конце 80-х я наткнулся на какой-то код на Фортране, который делал это в реальном времени. Оказывается, это действительно хороший способ имитировать потоки в ОС, в которой их нет. Вы просто помещаете всю программу (ваш планировщик) в цикл и вызываете свои «подпрограммы потоков» одну за другой. Сами подпрограммы потоков представляют собой циклы, которые повторяются до тех пор, пока не произойдет одно из ряда условий (часто одно из них - определенное количество время прошло). Это «кооперативная многозадачность», в которой каждый поток должен время от времени отказываться от ЦП, чтобы другие не истощались. Вы можете вложить вызовы подпрограммы цикла для имитации приоритета потока группы.

ТЕД
источник
1

В дополнение к уже упомянутым примерам goto, идиома do ... while (0) иногда используется в определении макроса, чтобы обеспечить скобки в определении и при этом заставить компилятор работать с добавлением точки с запятой в конец вызов макроса.

http://groups.google.com/group/comp.soft-sys.ace/browse_thread/thread/52f670f1292f30a4?tvc=2&q=while+(0)

Дэн
источник
0

Я согласен с большинством постеров об использовании в качестве тонко замаскированного goto. Макросы также упоминались как потенциальная мотивация для написания кода в этом стиле.

Я также видел, как эта конструкция использовалась в смешанных средах C / C ++ как исключение для бедняков. «Do {} while (false)» с «break» можно использовать для перехода к концу блока кода, если в цикле обнаруживается что-то, что обычно требует исключения.

Я также отправил эту конструкцию, используемую в магазинах, где применяется идеология «единого дохода на функцию». Опять же, это вместо явного «goto» - но мотивация состоит в том, чтобы избежать множественных точек возврата, а не «пропустить» код и продолжить фактическое выполнение внутри этой функции.

Stan Graves
источник
0

Я работаю с Adobe InDesign SDK, и в примерах InDesign SDK почти все функции написаны таким образом. Это связано с тем, что функции обычно очень длинные. Где вам нужно выполнить QueryInterface (...), чтобы получить что-либо из объектной модели приложения. Так что обычно каждый QueryInterface сопровождается неудачей if, перерыв.

Кугель
источник
0

Многие уже заявили о сходстве между этой конструкцией и a gotoи отдали предпочтение goto. Возможно, в прошлом у этого человека была среда, в которой goto были строго запрещены правилами кодирования?

Марк Рэнсом
источник
0

Другая причина, о которой я могу думать, заключается в том, что он украшает фигурные скобки, тогда как я считаю, что новые стандартные голые скобки C ++ не подходят (ISO C не любит их). Иначе заглушить статический анализатор вроде пуха.

Не уверен, зачем они вам нужны, возможно, переменная область видимости или преимущество с отладчиком.

См. Раздел « Тривиальный цикл Do While» и « Скобки хороши» из C2.

Чтобы прояснить мою терминологию (которая, как мне кажется, следует стандартному использованию):

Голые брекеты :

init();
...
{
c = NULL;
mkwidget(&c);
finishwidget(&c);
}
shutdown();

Пустые фигурные скобки (NOP):

{}

например

while (1)
   {}  /* Do nothing, endless loop */

Блок :

if (finished)
{
     closewindows(&windows);
     freememory(&cache);
}

который станет

if (finished)
     closewindows(&windows);
freememory(&cache);

если фигурные скобки удалены, изменяя тем самым поток выполнения, а не только объем локальных переменных. Таким образом, не «отдельно стоящий» или «голый».

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

mctylr
источник
В самом деле? Это позор. Одна из немногих вещей, которые мне нравились в C, заключалась в том, что он позволял объявлять новую вложенную область видимости где угодно.
TED
1
Голые скобки иногда помогают исправить странные сбои. См. Blogs.msdn.com/oldnewthing/archive/2004/05/20/135841.aspx .
Брайан
1
В C ++ блок (то есть ваши «голые скобки») можно использовать везде, где разрешена одна инструкция.
Бен Фойгт
@BenVoigt Пустые фигурные скобки, т.е. NOP отличается от «голых фигурных скобок», которые представляют собой блок, добавленный вокруг линейной последовательности инструкций. Например, `printf (" Привет "); {путчар (','); putchar (0x20); } printf ("world! \ n"); `где фигурные скобки не являются частью управления циклом или переходом.
mctylr
@mctylr: Я не говорил о пустых скобках.
Бен Фойгт
0

Это надуманный способ подражать a, GOTOпоскольку эти два практически идентичны:

// NOTE: This is discouraged!
do {
    if (someCondition) break;
    // some code be here
} while (false);
// more code be here

и:

// NOTE: This is discouraged, too!
if (someCondition) goto marker;
// some code be here
marker:
// more code be here

С другой стороны, оба эти действия действительно должны выполняться с помощью ifs:

if (!someCondition) {
    // some code be here
}
// more code be here

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

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

Я не знаю ни одного C-подобного языка, где do / while на самом деле является идиоматическим решением для чего-либо.

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

Алан Слива
источник
1
Алан, do..while(false)это не для выполнения "неопределенного" количества раз, это для одного выполнения .
Дмитрий
2
Он выполняется неопределенное количество раз, если у вас есть условный continueоператор в конце, как я показал. К undefinedI просто означает , что вы не знаете , является ли это более чем один раз , если вы не можете предсказать , будет ли выполняться условия , при определенной итерации выполняется. Без каких-либо continues, do..while(false)будет запускаться один раз, но также без каких-либо breaks в нем while(true)будет работать вечно, поэтому «поведение по умолчанию» на самом деле не имеет значения, чтобы понять, что может сделать с циклами.
Алан Плам,
Это полезно, когда вы определяете макрос с несколькими операторами. Если вы заключите их в do / while (false), вы можете использовать макрос в операторе if / else, как и любой другой вызов функции. объяснение см. на сайте unknowntheory.com/TechPapers/ while.htm
Джон Пэкуин,
5
Кто-то не понимает семантику continue. continueНЕ повторяет цикл. « continueОператор должен встречаться только в операторе итерации и вызывает передачу управления в часть продолжения цикла наименьшего включающего оператора итерации , то есть в конец цикла».
Бен Фойгт
-1, два верхних утверждения не идентичны по причинам, указанным @BenVoigt.
cmh
0

Некоторые кодеры предпочитают иметь только один выход / возврат из своих функций. Использование манекена do {....} while (false); позволяет «выйти» из фиктивного цикла после того, как вы закончите, и все еще иметь один возврат.

Я кодировщик Java, поэтому мой пример будет примерно таким:

import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class p45
{
    static List<String> cakeNames = Arrays.asList("schwarzwald torte", "princess", "icecream");
    static Set<Integer> forbidden = Stream.of(0, 2).collect(Collectors.toSet());

    public static  void main(String[] argv)
    {
        for (int i = 0; i < 4; i++)
        {
            System.out.println(String.format("cake(%d)=\"%s\"", i, describeCake(i)));
        }
    }


    static String describeCake(int typeOfCake)
    {
        String result = "unknown";
        do {
            // ensure type of cake is valid
            if (typeOfCake < 0 || typeOfCake >= cakeNames.size()) break;

            if (forbidden.contains(typeOfCake)) {
                result = "not for you!!";
                break;
            }

            result = cakeNames.get(typeOfCake);
        } while (false);
        return result;
    }
}
Дэвид Янг
источник
0

В таких случаях я использую

switch(true) {
   case condution1:
      ...
      break;
   case condution2:
      ...
      break;
}
Женя Остроушко
источник
-1

Это забавно. Вероятно, внутри цикла есть разрывы, как говорили другие. Я бы сделал это так:

while(true)
{
   <main code for function>
   break; // at the end.
}
fastcodejava
источник
2
С потенциалом бесконечного зацикливания? do..while(false)всегда выходит, while(true)более рискованно.
Дмитрий
1
while(true)является правильной идиомой для большинства языков. Вы часто найдете его в приложениях с графическим интерфейсом в качестве основного цикла программы. Поскольку вы в основном предполагаете, что программа не должна умереть, пока ей не скажут об этом, a do..while(false)вызовет всевозможные надуманные логики. Этот подход может быть более рискованным с точки зрения перфекциониста, но он семантически проще и, следовательно, менее подвержен ошибкам для программистов (извините, Скайнет).
Алан Плам,
2
@dmitry do{...}while(false)точно такой же, какwhile(true){ .. break;}
N 1.1
4
@ N1.1: Нет continue, они не такие.
Бен Фойгт