Почему бы не вызвать явный провал, а не явный разрыв для операторов switch? - PullRequest
4 голосов
/ 09 августа 2011

Это не вопрос C #, а C * версия switch, которая заставляет меня задать вопрос.

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

В C # компилятор не позволит вам перейти от одного оператора case к следующему (если только оператор case не пуст), и все же он заставляет вас ставить явный break в конце каждого оператора. один. Подавляющее большинство switch утверждений, которые я пишу, не проваливаются.

int x = 4;
string result;

switch (x)
{
case 1:
   result = "One";
   break;
case 2:
   result = "A couple";
   break;
case 3:
case 4:
   result = "Three or four";
   break;
/*
case 5:
   result = "Five";   // Here be an error! A common typo for me!!!
*/
default:
   result = "Five or more";
   break;
}

Приведенный выше пример придуман, чтобы показать возможности. Количество раз, когда я действительно проваливаюсь (как между 3 и 4 выше), минимально. Если я удалю комментарии из случая 5 выше, компилятор C # поймает это как ошибку. Почему я должен это исправить вручную, если компилятор прекрасно знает, что я пытаюсь сделать?

Не лучше ли следующее?

int x = 4;
string result;

switch (x)
{
case 1:
   result = "One";
case 2:
   result = "A couple";
case 3:
   continue;   // or even goto 4
case 4:
   result = "Three or four";
/*
case 5:
   result = "Five";   // This would not longer be an error!! Hooray!
*/
default:
   result = "Five or more";
}

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

Компилятор все еще мог бы кричать на меня, если бы я забыл выражение continue в случае 3. Хотя это случалось бы не очень часто, и я был бы рад за помощь. На самом деле, вероятность того, что я пропустил заполнение скелетного кода, в этом случае довольно высока. Полезно. Сказать мне, что я забыл заявление break, никогда не помогает. Просто радует компилятор.

Похоже, что это, вероятно, просто задержка от C (что позволяет вам проваливаться, даже если у вас есть код в операторе case). Есть ли более глубокая причина, по которой я не вижу?

Я смотрел какой-то код компилятора только этим утром, и в switch были сотни case операторов, которые ничего не делали, кроме возврата операционных кодов. У каждого из них было break заявление. Так много печатать и беспорядок ...

Что думают люди? Почему второй вариант не лучший по умолчанию?

Ответы [ 3 ]

6 голосов
/ 09 августа 2011

Обоснование утверждений C # switch заключается в том, что поведение C состоит в том, что случаи не выполняются, если вы явно не завершите работу с оператором, подобным break, return или goto.Это означает, что все, кто знаком с C (который, вероятно, является большинством программистов на C #), будут ожидать, что синтаксис C # switch будет означать примерно то же самое.Если бы дизайнеры C # делали случаи, когда не проваливались, код делал бы то же самое , что ожидают пользователи!

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

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

1 голос
/ 09 августа 2011

операторы switch действительно блестят в том случае, когда происходят подобные вещи (вместо ifs)

switch (my_var) {
    case 1:
    case 2:
    case 3:
    case 4:
        do_something();
        break;
    case 5:
    case 6:
    case 7:
    case 8:
        do_something else();
        break;
}

Это заменяет либо сильно вложенные операторы if, либо гигантские операторы if с ands в них.

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

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

0 голосов
/ 09 августа 2011

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

Причина, по которой C # не имеет неявного провала, заключается в том, что в большинстве случаев это ошибка. Причина того, что C # не имеет неявного перерыва, заключается в том, что это будет сюрпризом для программистов на C, C ++ и Java. И это даже не сгенерирует предупреждение? Тихие неожиданные неудачи очень плохи.

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

...