Почему мы нуждаемся в перерыве после операторов выбора?

Почему компилятор автоматически не помещает операторы завершения после каждого блока кода в переключателе? Это по историческим причинам? Когда Вы хотели бы, чтобы несколько блоков кода выполнились?

92
задан Paul Bellora 7 June 2013 в 20:33
поделиться

12 ответов

Иногда полезно иметь несколько вариантов, связанных с одним и тем же блоком кода, например

case 'A':
case 'B':
case 'C':
    doSomething();
    break;

case 'D':
case 'E':
    doSomethingElse();
    break;

и т. Д. Просто пример.

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

93
ответ дан 24 November 2019 в 06:28
поделиться

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

case THIS:
case THAT:
{
    code;
    break;
}

Или вы можете сделать что-то вроде:

case THIS:
{
   do this;
}
case THAT:
{
   do that;
}

Каскадным способом.

На самом деле подвержены ошибкам / путанице, если вы спросите меня.

4
ответ дан 24 November 2019 в 06:28
поделиться

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

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

31
ответ дан 24 November 2019 в 06:28
поделиться

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

14
ответ дан 24 November 2019 в 06:28
поделиться

Почему компилятор не помещает автоматически операторы break после каждого блока кода в переключателе?

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

Это по историческим причинам? Когда вы хотите, чтобы выполнялось несколько блоков кода?

Это в основном для совместимости с C, и, возможно, это древний прием с тех времен, когда ключевые слова goto бродили по земле. Он действительно , конечно же, позволяет использовать некоторые удивительные вещи, такие как Устройство Даффа , но то, за или против, это аргумент… в лучшем случае.

7
ответ дан 24 November 2019 в 06:28
поделиться

Java является производным от C, наследие которого включает метод, известный как Устройство Даффа . Это оптимизация, основанная на том факте, что контроль переходит от одного случая к другому, в отсутствие разрыва ; оператора. К тому времени, когда C был стандартизирован, такого кода «в дикой природе» было достаточно, и было бы контрпродуктивно менять язык, чтобы разрушить такие конструкции.

3
ответ дан 24 November 2019 в 06:28
поделиться

Java происходит от C, а это синтаксис от C.

Бывают случаи, когда вы хотите, чтобы несколько операторов case имели только один путь выполнения. { {1}} Ниже приведен образец, который покажет вам, сколько дней в месяце.

class SwitchDemo2 {
    public static void main(String[] args) {

        int month = 2;
        int year = 2000;
        int numDays = 0;

        switch (month) {
            case 1:
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
            case 12:
                numDays = 31;
                break;
            case 4:
            case 6:
            case 9:
            case 11:
                numDays = 30;
                break;
            case 2:
                if ( ((year % 4 == 0) && !(year % 100 == 0))
                     || (year % 400 == 0) )
                    numDays = 29;
                else
                    numDays = 28;
                break;
            default:
                System.out.println("Invalid month.");
                break;
        }
        System.out.println("Number of Days = " + numDays);
    }
}
29
ответ дан 24 November 2019 в 06:28
поделиться

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

0
ответ дан 24 November 2019 в 06:28
поделиться

Что касается исторических данных, Тони Хоар изобрел оператор case в 1960-х, во время революции «структурного программирования». Оператор case Тони поддерживает несколько меток для каждого case и автоматический выход без отвратительных операторов break . Требование явного разрыва исходило из линии BCPL / B / C. Деннис Ритчи пишет (в ACM HOPL-II):

Например, конечный регистр, который ускользает из оператора включения BCPL, отсутствовал в языке , когда мы его изучили в 1960-х годах, и поэтому перегрузка ключевое слово break для выхода из операторов switch B и C обязано дивергентной эволюции, а не сознательным изменениям.

Мне не удалось найти никаких исторических работ о BCPL, но комментарий Ричи предполагает, что разрыв был более или менее исторической случайностью. Позднее BCPL исправил проблему, но, возможно, Ричи и Томпсон были слишком заняты изобретением Unix, чтобы беспокоиться о таких деталях: -)

3
ответ дан 24 November 2019 в 06:28
поделиться

Отсутствие автоматического прерывания, добавляемого компилятором, позволяет использовать переключатель / регистр для проверки таких условий, как 1 <= a <= 3 , удалив оператор break из 1 и 2.

switch(a) {
  case 1: //I'm between 1 and 3
  case 2: //I'm between 1 and 3
  case 3: //I'm between 1 and 3
          break;
}
0
ответ дан 24 November 2019 в 06:28
поделиться

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

-1
ответ дан 24 November 2019 в 06:28
поделиться

С провалом футляра можно делать разные интересные вещи.

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

switch (someValue)
{
    case extendedActionValue:
        // do extended action here, falls through to normal action
    case normalActionValue:
    case otherNormalActionValue:
        // do normal action here
        break;
}

Конечно, легко забыть оператор break в конце случая и вызвать неожиданное поведение. Хорошие компиляторы предупредят вас, если вы опустите оператор break.

13
ответ дан 24 November 2019 в 06:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: