Подтвердить что ты не робот

Почему С# имеет разрыв, если он не является обязательным?

Когда я создаю оператор switch в VS2008 С#, как это (надуманный):

switch (state) {
    case '1':
        state = '2';
    case '2':
        state = '1';
}

он жалуется, что мне не разрешено пропустить:

Элемент управления не может проваливаться с одного ярлыка case ('case' 1 '(0x31):') на другой

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

4b9b3361

Ответ 1

Из уст лошади (MSDN) Почему оператор С# switch, предназначенный для того, чтобы не разрешить провал, но все же требует перерыва?.

Цитирование выделенных битов, поэтому они не позволяют проваливаться:

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

В С# оператор switch требует, чтобы в конце дела выполнялось явное управление потоком, либо break, goto, return, либо throw. Если разработчик желает оспаривать семантику, это может быть достигнуто явным goto в конце case case.

И вот почему он не автоматический:

В результате правил С#, требующих явного управления потоком в конце блока case (чаще всего это разрыв), многие люди спрашивают, почему поведение просто не было изменено, так что провал не был происходят. То есть, не требуйте разрыва, просто измените семантику переключателя, чтобы он не имел провалов для случаев. Причина, по которой это не было сделано, заключалась в том, что разработчикам, которые очень привыкли к С++, не было бы трудно понять, что делает оператор switch.

Ответ 2

В основном, чтобы он был более знаком с разработчиками C/С++/Java. Лично я думаю, что это была ошибка, но это рассуждение.

Я бы предпочел принудительный блок:

case '1':
{
}

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

case '0':
case '1':
{
}

Также неплохо было бы более просто перечислить несколько случаев:

case '0', '1':
{
}

О, и небольшая нить-выбор о вашем описании существующего языка: вам не обязательно иметь перерыв. Это просто, что конец дела должен быть недостижим. Вы также можете иметь throw, goto или return. Могут быть и другие, которых я тоже пропустил:)

Ответ 3

Вам разрешено пропустить, но вы должны сделать это явно с помощью ключевого слова goto:

switch (state) {
    case '1':
        state = '2';
        goto case '2';
    case '2':
        state = '1';
        break;
}

Вы можете break или goto в С#, но то, что вы не можете сделать, это не состояние, которое вы хотите, потому что это потенциальный источник труднодоступных ошибок.

Намного легче заметить, что ваш код говорит goto, когда вы хотели break (или наоборот), чем это заметили, что вы забыли добавить либо.

Это может показаться глупым, но многие усталые двухчасовые поиски причины ошибки С++ заканчиваются внезапным осознанием того, что вы забыли добавить break, и ваш код проваливается все время. С# избегает этого, заставляя вас указать, что вы хотите.

Ответ 4

Если у вас нет кода в случае 1, вам разрешено провалиться, поэтому вы можете сказать, что "все эти случаи разделяют этот кусок кода"