Случай переключения PHP по умолчанию

Будет ли оцениваться значение оператора switch по умолчанию, если перед ним есть соответствующий случай?

ex:

switch ($x) {
  case ($x > 5): print "foo";
  case ($x%2 == 0): print "bar";
  default: print "nope";
}

так что для x = 50 вы увидите foo и bar или foo и bar и nope?


person beth    schedule 10.08.2012    source источник
comment
Вы пробовали запустить этот код?   -  person GreenMatt    schedule 10.08.2012
comment
Если нет совпадения регистра, будет выполнен случай по умолчанию.   -  person Tony M    schedule 10.08.2012
comment
FYI case ($x > 5) оценивается как case 1: или case true:.   -  person Matt    schedule 10.08.2012
comment
Без break ваш код будет пытаться соответствовать всем условиям. С break он остановится на 1-м совпадении.   -  person N.B.    schedule 10.08.2012
comment
Я не хочу, чтобы это остановилось на первом матче. Я хочу, чтобы он выполнял код для всех совпадающих случаев.   -  person beth    schedule 10.08.2012
comment
Без перерывов в вашем коде он выполнит первый соответствующий случай и каждый последующий случай.   -  person Adam    schedule 10.08.2012


Ответы (4)


Да, если "перерыва" нет, то будут выполнены все действия, следующие за первым совпавшим case. Поток управления будет «проваливаться» через все последующие case и выполнять все действия в рамках каждого последующего case, пока не встретится оператор break; или пока не будет достигнут конец оператора switch.

В вашем примере, если $x имеет значение 50, вы фактически увидите "nope".

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

Ваш пример необычен тем, что он будет отображать "foo" только тогда, когда $x имеет значение 0. (На самом деле, когда $x имеет значение 0, то, что вы увидите, будет «foo bar nope».)

Оценивается выражение, следующее за ключевым словом case, которое в вашем случае, например, возвращает 0 (если условная проверка ложна) или 1 (если условная проверка верна). И именно это значение (0 или 1) switch будет сравнивать с $x.

person spencer7593    schedule 10.08.2012

Будет ли оцениваться значение оператора switch по умолчанию, если перед ним есть соответствующий случай?

В большинстве case этого не должно быть, потому что там часто будут break. Однако в вашем случае это также пойдет на default.

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

$x = 10;

switch (true) {
  case ($x > 5):
      print "foo";

  case ($x%2 == 0):
      print "bar";

  default:
      print "nope";
}

Напечатает foobarnope. Итак, чтобы ответить на ваш вопрос: да :-)

person PeeHaa    schedule 10.08.2012
comment
печатает foobarnope. Как только какой-либо случай будет истинным, будут выполняться все последующие случаи, включая значения по умолчанию, вплоть до разрыва (или конца переключения). codepad.viper-7.com/sjHYeZ - person Jonathan Kuhn; 10.08.2012

Выключатели так не работают.

Согласно руководству:

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

Оценка, как

case ($x > 5):

просто приравнивается к

case true:

or

case false:

в зависимости от значения $x, потому что ($x > 5) — это ОЦЕНКА, а не ЗНАЧЕНИЕ. Переключатели сравнивают значение параметра, чтобы увидеть, соответствует ли оно какому-либо из case.

switch($x) {
    case ($x > 5): // $x == ($x > 5)
        echo "foo";
        break;
    case ($x <= 5): // $x == ($x <= 5)
        echo "bar"
        break;
    default:
        echo "default";
        break;
}

Сравнение в приведенном выше коде эквивалентно

if ($x == ($x > 5)) {
    echo "foo";
} elseif ($x == ($x < 5)) {
    echo "bar";
} else {
    echo "five";
}

который (когда $x == 50) эквивалентен

if ($x == true) {
    echo "foo";
} elseif ($x == false) {
    echo "bar";
} else {
    echo "five";
}

что эквивалентно

if (true) { // $x == true is the same as saying "$x is truthy"
    echo "foo";
} elseif (false) {
    echo "bar";
} else {
    echo "five";
}

Однако, ЕСЛИ, вы использовали свой оператор switch так, как он и должен использоваться (для сравнения параметра с конкретными значениями):

switch ($x) {
    case 50:
        echo "foo ";
    case 30:
        echo "bar ";
    default:
        echo "foo-bar";
}

и $x == 50, ваш вывод будет

foo bar foo-bar

в связи с тем, что у вас нет break в ваших делах.

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

switch ($x) {
    case 50:
        echo "foo ";
        break;
    case 30:
        echo "bar ";
        break;
    default:
        echo "foo-bar";
        break;
}

Выход:

foo 
person Matt    schedule 10.08.2012
comment
Нет, ты этого не сделал. Прочитайте, что вы написали. Вы сказали, что такие переключатели нельзя использовать, и вы ошибаетесь - можно, и никто никому не мешает. Публиковать полуправильный ответ ужасно, кто-то войдет, прочтет то, что вы написали, и подумает, что вы были правы, хотя это было не так. - person N.B.; 10.08.2012
comment
Оператор switch OP совершенно действителен. Наличие вычислений в кейсах — это совершенно корректный и очень желательный код. Ваш ответ показывает только один тип использования оператора. - person Buggabill; 10.08.2012
comment
@Matt - в логике, которую вы пытаетесь объяснить, нет ничего плохого, неправильно ваше объяснение оператора switch. Оператор Switch ведет себя точно так же, как оператор if. Вы можете сравнить значения, чтобы получить true или false. switch - это просто придуманное удобство, поэтому не нужно набирать 100 комбинаций if/else и вкладывать код в забвение. - person N.B.; 10.08.2012
comment
@buggabill Я не уверен, что это крайне желательно, но это действительно так. Моя точка зрения заключалась в том, что его не следует использовать таким образом, если он полностью не понимает, почему он используется. - person Matt; 10.08.2012
comment
@Н.Б. Так ты хочешь сказать, что case ($x > 5) это то же самое, что if ($x > 5)? Потому что это не так. Это соответствует if ($x == ($x > 5)), и ОП должен это знать. - person Matt; 10.08.2012
comment
@ Мэтт, извини, но ты ошибаешься. Оператор switch ведет себя точно так же, как if. case $x > 50: точно такой же, как if($x > 50), вот и все. - person N.B.; 10.08.2012
comment
@Н.Б. мой ответ был ответом на последний вопрос ОП: so for x = 50, you'd see foo and bar, or foo and bar and nope? Очевидно, она не понимает, как выполняются сравнения в switch, и я уверен, что этот ответ помог прояснить это. - person Matt; 10.08.2012
comment
@Н.Б. Операция switch аналогична серии операторов IF для одного и того же выражения. Во многих случаях вам может потребоваться сравнить одну и ту же переменную (или выражение) со многими различными значениями и выполнить другой фрагмент кода в зависимости от того, какому значению оно соответствует. Это именно то, для чего предназначен оператор switch. - person Matt; 10.08.2012
comment
@Н.Б. stackoverflow.com/questions/11904754/switch-evaluations Надеемся, что ответ на этот вопрос разрешит этот наш спор. Если я ошибаюсь, я удалю свой ответ и присужу вам 500 наград. Если я прав, я ожидаю, что вы удалите свои комментарии и свой -1. - person Matt; 10.08.2012
comment
@N.B., @Matt абсолютно прав насчет того, как работает переключатель. если бы у вас был переключатель switch($x){ case 0: echo "hi"; break; }, не был бы эквивалентным оператор if if($x == 0)...? так почему бы переключателю OP не быть равным if($x == ($x > 5))...? вы как-то теряете уравнение случая? - person Jonathan Kuhn; 10.08.2012
comment
@ Мэтт, одна строчка, с которой я не согласен. Вывод для приведенного выше кода всегда будет по умолчанию, если только $x == 1. Это неверно. Например, в сравнении $x==($x > 5) есть неявное преобразование $x в логическое значение, которое будет оцениваться как true, пока $x!=0. Если $x=0, это утверждение фактически вернет true, поскольку $x будет ложным, а $x›5 ложным, поэтому вы получите false==false. Если $x=от 1 до 5, оператор возвращает false, так как любое число, отличное от 0, преобразуется в логическое значение true. поэтому оператор становится true==false. любое число выше 5 оператор вернет true true == true. - person Jonathan Kuhn; 10.08.2012

Было бы проще попробовать самому.

Но в любом случае, если вы не используете break в кейсе, будут выполнены все кейсы, следующие за ним (включая дефолтный).

person Oussama Jilal    schedule 10.08.2012
comment
Это правда, что помимо stackoverflow есть места, где можно найти ответы на вопросы, но когда мы это делаем, никто не получает репутацию ;-) - person beth; 10.08.2012