Оператор switch с возвратом - правильность кода

Скажем, у меня есть код на C с примерно такой структурой:

switch (something)
{
    case 0:
      return "blah";
      break;

    case 1:
    case 4:
      return "foo";
      break;

    case 2:
    case 3:
      return "bar";
      break;

    default:
      return "foobar";
      break;
}

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

Как вы думаете? Удалось ли их удалить? Или вы сохраните их для повышения "правильности"?

Ответ 1

Удалить инструкции break. Они не нужны, и, возможно, некоторые компиляторы выдадут предупреждения "недостижимый код".

Ответ 2

Я бы взял совсем другой подход. Не используйте RETURN в середине метода/функции. Вместо этого просто поместите возвращаемое значение в локальную переменную и отправьте ее в конце.

Лично я считаю следующее более читаемым:

String result = "";

switch (something) {
case 0:
  result = "blah";
  break;
case 1:
  result = "foo";
  break;
}

return result;

Ответ 3

Лично я удаляю возвращаемые данные и сохраняю перерывы. Я бы использовал оператор switch, чтобы присвоить значение переменной. Затем верните эту переменную после оператора switch.

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

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

Ответ 4

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

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

Ответ 5

Удалите их. Идиоматично возвращаться из операторов case, а в противном случае это "недостижимый код".

Ответ 6

Я бы удалил их. В моей книге такой мертвый код следует считать ошибками, потому что он заставляет вас сделать двойной прием и спросить себя: "Как мне выполнить эту строку?"

Ответ 7

Я бы обычно писал код без них. ИМО, мертвый код, как правило, указывает на небрежность и/или отсутствие понимания.

Конечно, я бы тоже подумал о чем-то вроде:

char const *rets[] = {"blah", "foo", "bar"};

return rets[something];

Изменить: даже с отредактированным сообщением эта общая идея может работать нормально:

char const *rets[] = { "blah", "foo", "bar", "bar", "foo"};

if ((unsigned)something < 5)
    return rets[something]
return "foobar";

В какой-то момент, особенно если входные значения разрежены (например, 1, 100, 1000 и 10000), вы хотите использовать разреженный массив. Вы можете реализовать это как дерево или карту достаточно хорошо (хотя, конечно, в этом случае переключатель все еще работает).

Ответ 8

Я бы сказал, удалить их и определить ветку по умолчанию:

Ответ 9

Не было бы лучше иметь массив с

arr[0] = "blah"
arr[1] = "foo"
arr[2] = "bar"

и do return arr[something];?

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

Ответ 10

Для "правильности" единственная запись, одиночные блоки выхода - хорошая идея. По крайней мере, они были, когда я закончил компьютерную науку. Поэтому я, вероятно, объявляю переменную, назначаю ее в коммутатор и возвращаю один раз в конце функции

Ответ 11

Как вы думаете? Удалось ли их удалить? Или вы сохраните их для повышения "правильности"?

Хорошо удалить их. Использование return точно сценарий, в котором break не должен использоваться.

Ответ 12

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

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

Ответ 13

Интересно. По мнению большинства из этих ответов, избыточное утверждение break является ненужным беспорядком. С другой стороны, я прочитал инструкцию break в коммутаторе как "закрытие" дела. case блоки, которые не заканчиваются на break, склонны выпрыгивать на меня как потенциальное падение, хотя ошибки.

Я знаю, что это не так, как там, где return вместо break, но то, как мои глаза "читают" блоки блоков в коммутаторе, поэтому я лично предпочел бы, чтобы каждый case был в паре с break. Но многие компиляторы действительно жалуются на break после того, как return становится излишним/недоступным, и, судя по всему, я все равно остаюсь в меньшинстве.

Итак, избавьтесь от break после return.

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

Ответ 14

Я лично теряю break s. Возможно, одним из источников этой привычки является программирование оконных приложений для приложений Windows:

LRESULT WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
        case WM_SIZE:
            return sizeHandler (...);
        case WM_DESTROY:
            return destroyHandler (...);
        ...
    }

    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

Я лично считаю этот подход намного проще, кратким и гибким, чем объявление возвращаемой переменной, заданной каждым обработчиком, а затем возвращающее ее в конце. Учитывая этот подход, break являются избыточными и поэтому должны идти - они не служат никакой полезной цели (синтаксически или IMO визуально) и только раздувают код.

Ответ 15

Я думаю, что * break * s есть для этой цели. Это значит, что "идеология" программирования жива. Если мы хотим просто "запрограммировать" наш код без логической согласованности, возможно, он будет читабельен вам сейчас, но попробуйте завтра. Попробуйте объяснить это своему боссу. Попробуйте запустить его на Windows 3030.

Bleah, идея очень проста:


Switch ( Algorithm )
{

 case 1:
 {
   Call_911;
   Jump;
 }**break**;
 case 2:
 {
   Call Samantha_28;
   Forget;
 }**break**;
 case 3:
 {
   Call it_a_day;
 }**break**;

Return thinkAboutIt?1:return 0;

void Samantha_28(int oBed)
{
   LONG way_from_right;
   SHORT Forget_is_my_job;
   LONG JMP_is_for_assembly;
   LONG assembly_I_work_for_cops;

   BOOL allOfTheAbove;

   int Elligence_says_anyways_thinkAboutIt_**break**_if_we_code_like_this_we_d_be_monkeys;

}
// Sometimes Programming is supposed to convey the meaning and the essence of the task at hand. It is // there to serve a purpose and to keep it alive. While you are not looking, your program is doing  // its thing. Do you trust it?
// This is how you can...
// ----------
// **Break**; Please, take a **Break**;

/* Только незначительный вопрос. Сколько у вас было кофе при чтении выше? ЭТО. Перерывы система иногда */