Должны ли операторы switch всегда содержать предложение по умолчанию? - PullRequest
220 голосов
/ 10 января 2011

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

  1. Есть ли разумная причина всегда включать выражение по умолчанию?

  2. Зависит ли этот язык?Я не помню, какой язык я использовал в то время - может быть, это относится к некоторым языкам, а не к другим?

Ответы [ 20 ]

3 голосов
/ 14 ноября 2013

По крайней мере, это не обязательно в Java.Согласно JLS, он говорит, что может присутствовать как минимум один случай по умолчанию.Это означает, что ни один случай по умолчанию не приемлем.Время от времени также зависит от контекста, который вы используете оператор switch.Например, в Java для следующего блока переключателей не требуется регистр по умолчанию

private static void switch1(String name) {
    switch (name) {
    case "Monday":
        System.out.println("Monday");
        break;
    case "Tuesday":
        System.out.println("Tuesday");
        break;
    }
}

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

    private static String switch2(String name) {
    switch (name) {
    case "Monday":
        System.out.println("Monday");
        return name;

    case "Tuesday":
        System.out.println("Tuesday");
        return name;

    default:
        return name;
    }
}

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

2 голосов
/ 20 октября 2016

Случай по умолчанию может не понадобиться в переключателе, используемом enum.когда switch содержит все значения, регистр по умолчанию никогда не будет выполнен.Так что в этом случае это не обязательно.

2 голосов
/ 06 сентября 2016

Поскольку MISRA C говорит так:

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

При этом я рекомендую не следовать следующим требованиям MISRA C для большинства программ:

  • Это защитное программирование руководство по стилю не заботится , что допустимы только некоторые значения - если переменная физически способна принимать значение, даже если это будетошибка, вы должны справиться с этим.Большинство программного обеспечения предпочитают печатать трассировку стека вместо «обработки» ошибок (как упомянуто Офиром Йоктаном).
  • У переключателей Enum, в частности, не должно быть предложения по умолчанию (как сказал Харлан Касслер).И, как наглядно демонстрирует Харлан, обработка недопустимых значений может быть выполнена вне коммутатора - точка, которая отсутствовала в обсуждении Мисры .
2 голосов
/ 29 января 2016

Если в операторе switch нет случая по умолчанию, поведение может быть непредсказуемым, если этот случай возникает в какой-то момент времени, что не было предсказуемо на этапе разработки.Хорошей практикой является включение default кейса.

switch ( x ){
  case 0 : { - - - -}
  case 1 : { - - - -}
}

/* What happens if case 2 arises and there is a pointer
* initialization to be made in the cases . In such a case ,
* we can end up with a NULL dereference */

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

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

2 голосов
/ 11 марта 2011

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

Однако я не согласен с Адрианом Смитом, что ваше сообщение об ошибке по умолчанию должно быть чем-то совершенно бессмысленным. Может быть необработанный случай, который вы не предвидели (и это своего рода точка), которую ваш пользователь в конечном итоге увидит, а сообщение типа «недоступно» совершенно бессмысленно и никому не помогает в этой ситуации. *

Показательный пример, сколько раз у вас был совершенно бессмысленный BSOD? Или фатальное исключение @ 0x352FBB3C32342?

2 голосов
/ 28 мая 2014

Это необязательное кодирование 'соглашение'. В зависимости от использования, является ли это необходимо или нет. Я лично считаю, что если вам это не нужно, его не должно быть. Зачем включать что-то, что не будет использоваться или недоступно пользователю?

Если возможности регистра ограничены (т. Е. Логическим значением), тогда предложением по умолчанию является избыточный !

2 голосов
/ 08 января 2014

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

1 голос
/ 10 января 2011

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

0 голосов
/ 02 июля 2019

Я полагаю, что это довольно специфично для языка, и для случая C ++ второстепенная точка для типа enum class .Который кажется более безопасным, чем традиционное перечисление.НО

Если вы посмотрите на реализацию std :: byte, она выглядит примерно так:

enum class byte : unsigned char {} ;

Источник: https://en.cppreference.com/w/cpp/language/enum

А также учтите это:

В противном случае, если T является типом перечисления, имеющим область видимости или область с фиксированным базовым типом, и если в braced-init-list есть только один инициализатор, и если преобразование из инициализатора в базовый тип имеет видне сужение, и если инициализация является прямой инициализацией списка, то перечисление инициализируется с результатом преобразования инициализатора к его базовому типу.

(начиная с C ++ 17)

Источник: https://en.cppreference.com/w/cpp/language/list_initialization

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

Однако мне действительно нравится то, что @Harlan Kassler сказал в своем посте, и я сам начну использовать эту стратегию в некоторых ситуациях.

Просто пример небезопасного enumкласс:

enum class Numbers : unsigned
{
    One = 1u,
    Two = 2u
};

int main()
{
    Numbers zero{ 0u };
    return 0;
}
0 голосов
/ 01 ноября 2017

Должны ли операторы switch всегда содержать предложение по умолчанию? Случаи переключения не могут существовать без случая по умолчанию, в случае переключателя значение по умолчанию вызовет значение переключателя switch(x), в этом случае x, если оно не совпадает ни с одним другим значением случая.

...