Кто решил (и на основе каких понятий), что switch
конструкция (на многих языках) должна использоваться break
в каждом утверждении?
Почему мы должны написать что-то вроде этого:
switch(a)
{
case 1:
result = 'one';
break;
case 2:
result = 'two';
break;
default:
result = 'not determined';
break;
}
(заметил это в PHP и JS; возможно, есть много других языков, использующих это)
Если switch
есть альтернатива if
, почему мы не можем использовать ту же конструкцию, что и для if
? То есть:
switch(a)
{
case 1:
{
result = 'one';
}
case 2:
{
result = 'two';
}
default:
{
result = 'not determined';
}
}
Говорят, что break
предотвращает выполнение блока, следующего за текущим. Но действительно ли кто-то сталкивался с ситуацией, когда возникла необходимость выполнения текущего и последующих блоков? Я не Для меня break
всегда есть. В каждом блоке. В каждом коде.
conditions
trejder
источник
источник
CASE
оператор эквивалентно гигантскому блоку if / elseif.case 'a': case 'A': case 'b': case 'B'
но в основном потому, что я не могу сделатьcase in [ 'a', 'A', 'b', 'B' ]
. Немного лучший вопрос, в моем текущем предпочтительном языке (C #), разрыв обязателен , и не существует неявного падения; забываниеbreak
- синтаксическая ошибка ...: \case TOKEN_A: /*set flag*/; case TOKEN_B: /*consume token*/; break; case TOKEN_C: /*...*/
break
он присутствует где-либо» - это значительно более простое правило для реализации, чем «Не испускать прыжок, еслиfallthrough
он присутствует вswitch
».Ответы:
C был одним из первых языков, у которого было
switch
утверждение в этой форме, и все другие основные языки унаследовали его оттуда, в основном предпочитая сохранять семантику C по умолчанию - они либо не думали о преимуществах его изменения, либо судили они менее важны, чем сохранение привычного поведения.Что касается того, почему C был разработан таким образом, он, вероятно, вытекает из концепции C как «переносной сборки».
switch
Утверждение в основном это абстракция таблицы отраслевой и таблица филиала также имеет неявное падение-через и требует дополнительной инструкции перехода , чтобы избежать этого.Таким образом, дизайнеры C также решили оставить семантику ассемблера по умолчанию.
источник
switchon
.when
.Потому что
switch
это не альтернативаif ... else
заявлениям на этих языках.Используя
switch
, мы можем сопоставить более одного условия за раз, что высоко ценится в некоторых случаях.Пример:
источник
more than one block ... unwanted in most cases
Я не согласен с вами.break
. Но да, насколько я знаю, устройство Даффа не работает в C #.C# does not support an implicit fall through from one case label to another
. Вы можете провалиться, но нет шансов случайно забыть перерыв.if..else
но в некоторых ситуацияхswitch..case
было бы предпочтительнее. Приведенный выше пример будет немного сложным, если мы используем if-else.Это было задано в связи с переполнением стека в контексте C: почему для оператора switch был нужен разрыв?
Подводя итог принятому ответу, это была, вероятно, ошибка. Большинство других языков, вероятно, просто следовали за C. Однако, некоторые языки, такие как C #, похоже, исправили это, допустив провал - но только когда программист явно говорит об этом (источник: ссылка выше, я сам не говорю на C #) ,
источник
/* FALLTHRU */
комментарий в ответе, связанный @Tapio выше, чтобы доказать, что вы это имели в виду.goto case
, как и ссылка, не иллюстрирует, почему это работает так хорошо. Вы по-прежнему можете составлять несколько случаев, как описано выше, но как только вы вставляете код, вам нужно иметь явное выражениеgoto case whatever
для перехода к следующему случаю, или вы получите ошибку компилятора. Если вы спросите меня, из двух, возможность суммировать дела, не беспокоясь о непреднамеренном провале из-за халатности, намного лучше, чем возможность явного провала с помощьюgoto case
.Я отвечу на примере. Если вы хотите указать количество дней в каждом месяце года, очевидно, что в некоторых месяцах 31, а в 30 - 1 28/29. Это будет выглядеть так,
Это пример, когда несколько случаев имеют одинаковый эффект и все сгруппированы вместе. Очевидно, была причина выбора ключевого слова break, а не конструкции if ... else if .
Главное, на что следует обратить внимание, это то, что оператор switch во многих похожих случаях - это не if ... else if ... else if ... else для каждого из случаев, а скорее if (1, 2, 3) ... еще, если (4,5,6) еще ...
источник
if
без какой-либо выгоды. Возможно, если бы в вашем примере было назначено имя или выполнялась работа по конкретному месяцу в дополнение к провалу, полезность провала была бы более очевидной? (не комментируя, ДОЛЖЕН ли кто-либо быть на первом месте)Существуют две ситуации, когда может произойти «провал» из одного дела в другое - пустой случай:
и непустой случай
Несмотря на ссылку на устройство Даффа , законные экземпляры для второго случая очень редки и, как правило, запрещены стандартами кодирования и помечены во время статического анализа. И там, где это найдено, это чаще всего происходит из-за упущения а
break
.Первое совершенно разумно и распространено.
Честно говоря, я не вижу причин для того,
break
чтобы синтаксический анализатор языка и языка знал, что пустое тело-регистр является провальным, а непустое - автономным.Жаль, что панель ISO C выглядит более озабоченной добавлением новых (нежелательных) и плохо определенных функций в язык, а не исправлением неопределенных, неуказанных или определяемых реализацией функций, не говоря уже о нелогичности.
источник
Не принуждение
break
позволяет сделать ряд вещей, которые в противном случае было бы трудно сделать. Другие отметили группирование случаев, для которых есть ряд нетривиальных случаев.Одним из случаев, когда крайне важно, чтобы его
break
не использовали , было устройство Даффа . Это используется для « развертывания » циклов, где это может ускорить операции, ограничивая количество требуемых сравнений. Я полагаю, что первоначальное использование допускало функциональность, которая раньше была слишком медленной с полностью свернутым циклом. В некоторых случаях он меняет размер кода на скорость.Рекомендуется заменить
break
соответствующий комментарий, если в кейсе есть какой-либо код. В противном случае кто-то исправит недостающееbreak
и внесет ошибку.источник
В C, где, как представляется, источник, блок кода
switch
оператора не является специальной конструкцией. Это обычный блок кода, такой же, как блок подif
оператором.case
иdefault
метки перехода внутри этого блока, особенно связанные сswitch
. Они обрабатываются так же, как обычные метки переходаgoto
. Здесь важно одно конкретное правило: метки перехода могут быть практически везде в коде, не прерывая поток кода.Как обычный блок кода, он не должен быть составным оператором. Метки тоже не обязательны. Это действительные
switch
утверждения в C:Сам стандарт C дает это в качестве примера (6.8.4.2):
Кроме того,
default
это тоже метка перехода, и, следовательно, она может быть где угодно, без необходимости быть последним случаем.Это также объясняет устройство Даффа:
Почему провал? Потому что в нормальном потоке кода в нормальном блоке кода ожидается переход к следующему оператору , так же, как вы ожидаете его в
if
блоке кода.Я предполагаю, что причиной этого была простота реализации. Вам не нужен специальный код для разбора и компиляции
switch
блока, заботясь о специальных правилах. Вы просто анализируете его, как любой другой код, и вам нужно только позаботиться о метках и выборе перехода.Интересный дополнительный вопрос из всего этого состоит в том, что следующие вложенные операторы печатают «Готово». или нет.
Стандарт C заботится об этом (6.8.4.2.4):
источник
Несколько человек уже упомянули идею соответствия множественным условиям, что время от времени очень ценно. Однако способность соответствовать нескольким условиям не обязательно требует, чтобы вы выполняли одно и то же с каждым соответствующим условием. Учтите следующее:
Есть два разных способа сопоставления множества условий. При выполнении условий 1 и 2 они просто переходят к одному и тому же фрагменту кода и делают одно и то же. С условиями 3 и 4, однако, хотя они оба заканчиваются вызовом
doSomething3And4()
, только 3 вызоваdoSomething3()
.источник
case 2
запуску кода , поэтому, если мы хотим быть правильными (и мы делаем) реальное имя функции должно бытьdoSomethingBecause_1_OR_2_OR_1AND2()
или что-то в этом роде (хотя законный код, в котором неизменяемый соответствует двум разным случаям, хотя хорошо написанный код практически отсутствует, так что, по крайней мере, так должно бытьdoSomethingBecause1or2()
)doSomething[ThatShouldBeDoneInTheCaseOf]1And[InTheCaseOf]2()
. Это не относится к логическому и / или.Чтобы ответить на два ваших вопроса.
Зачем C нужны перерывы?
Все сводится к корням Cs как «переносному ассемблеру». Где псевдо-код, как это было распространено:
Инструкция switch была разработана для обеспечения аналогичной функциональности на более высоком уровне.
У нас когда-нибудь есть выключатели без перерывов?
Да, это довольно часто, и есть несколько вариантов использования;
Во-первых, вы можете предпринять одно и то же действие в нескольких случаях. Мы делаем это, укладывая чехлы друг на друга:
Другой пример использования, распространенный в конечных автоматах, заключается в том, что после обработки одного состояния мы сразу хотим войти и обработать другое состояние:
источник
Оператор Break - это оператор прыжка, который позволяет пользователю выйти из ближайшего включающего переключателя (для вашего случая), в то время как, do, for или foreach. это так же просто, как это.
источник
Я думаю, что со всем написанным выше - главный результат этого потока заключается в том, что если вы хотите разработать новый язык - по умолчанию должно быть, что вам не нужно добавлять
break
оператор, и компилятор будет обрабатывать его так, как если бы вы это сделали.Если вам нужен тот редкий случай, когда вы хотите перейти к следующему случаю - просто заявите это с помощью
continue
заявления.Это может быть улучшено, так что только если вы используете фигурные скобки внутри кейса, это не будет продолжаться, так что пример с несколькими месяцами выше, выполняющими один и тот же точный код - всегда будет работать, как и ожидалось, без необходимости
continue
.источник
*
,&
, иstatic
т.д.