2012-08-10 2 views
0

J'ai récemment discuté de la manière dont switch gère les comparaisons et a besoin d'aide pour le régler.Commutateur d'évaluation

Si j'écris un switch comme:

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

Quelle déclaration if est-il équivalent à? A ou B?

// A 

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

// B 

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

Répondre

5

Pour tout le monde, permettez-moi de préciser:

Il est équivalent à B.

Ce n'est pas "les deux", ce n'est pas parfois le sien, parfois c'est l'autre, c'est toujours B. Pour comprendre pourquoi vous voyez parfois des résultats qui indiquent que cela pourrait être A, vous devez comprendre how type coercion works in PHP.

Si vous passez une valeur Falsey à l ' « argument » de switch et que vous utilisez expressions dans vos case s qui se traduisent par une valeur booléenne, ils ne correspondent si votre expression est évaluée à FALSE.


switch est essentiellement un grand arbre if/elseif qui effectue les comparaisons en vrac (== au lieu de ===) entre la valeur passée à switch (le côté gauche de l'expression) et l'expression dans les case s (à droite côté).

Ce can be proved tout à fait bien avec une variation sur votre code:

$x = 0; 

switch ($x) { 
    case $x > -1: // This is TRUE, but 0 == FALSE so this won't match 
    echo "case 1"; 
    case $x == -1: // This is FALSE, and 0 == FALSE so this will match 
    echo "case 2"; 
} 

Et si nous convertissons que les deux if/elseif arbres:

A:

$x = 0; 

if ($x > -1) { 
    // It matches here 
    echo "case 1"; 
} else if ($x == -1) { 
    // and not here 
    echo "case 2"; 
} 

B:

$x = 0; 

if ($x == ($x > -1)) { 
    // It doesn't match here 
    echo "case 1"; 
} else if ($x == ($x == -1)) { 
    // ..but here instead 
    echo "case 2"; 
} 
2

Ce commutateur cas est équivalent à B

Edit:

Si nous prenons par exemple que $ x est égal à 0:

$ x> 5 évaluera à false (et 0 est aussi faux), donc la première affichera la barre d'impression, mais la seconde affichera foo. Le commutateur sera transformé en quelque chose comme ceci:

switch ($x){ 
    case false: 
     echo "foo"; 
     break; 
    case true: 
     echo "bar"; 
     break; 
    default: 
     echo "five"; 
     break; 
} 

et imprimera foo (comme B)

Edit 2:

Je l'ai essayé ce qui m'a donné:

avec $ x = 0 => commutateur (foo), si A (bar), si B (foo)

avec $ x = 5 => switc h (cinq), si A (cinq), si B (cinq)

avec $ x = 7 => commutateur (foo), si A (foo), si B (foo)

+0

Je sais que c'est ** B **, mais je besoin de plus Certains des "commentaires" dans la documentation indiquent que cela pourrait être ** A ** – Matt

+1

J'ai édité la réponse – Oussama

2

Votre exemple est équivalent à B.

Si vous souhaitez utiliser la comparaison dans votre commutateur (et équivalent à A), vous pouvez écrire ceci:

switch (true) { // Use true instead of $x 
    case ($x > 5): 
     echo "foo"; 
     break; 
    case ($x < 5): 
     echo "bar"; 
     break; 
    default: 
     echo "five"; 
     break; 
} 
+0

Donc vous dites que le code ci-dessus serait équivalent à * * A **? – Matt

+0

Oui, c'est ce que je veux dire – Florent

0

J'étais le premier message avec "La réponse est B", mais SO ne l'a pas accepté parce que "le corps doit être au moins 30 caractères; vous avez entré 15"

est ici la preuve, en utilisant PHP 5.4.0.

<?php 

<?php 

function test($x) { 
    echo "Switch: "; 

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

    echo "\nA: "; 

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

    echo "\nB: "; 

    // B 

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

echo "Test with 6:\n\n"; 
test(6); 
echo "\n\nTest with 4:\n\n"; 
test(4); 
echo "\n\nTest with 5:\n\n"; 
test(5); 
echo "\n\nTest with true:\n\n"; 
test(true); 
echo "\n\nTest with false:\n\n"; 
test(false); 
echo "\n\n"; 

produit cette sortie:

 
    Test with 6: 

Switch: foo 
A: foo 
B: foo 

Test with 4: 

Switch: bar 
A: bar 
B: bar 

Test with 5: 

Switch: five 
A: five 
B: five 

Test with true: 

Switch: five 
A: five 
B: five 

Test with false: 

Switch: foo 
A: bar 
B: foo 
+0

Comment '$ x == ($ x> 5)' évalue à 'vrai' où' $ x == 6'? – Matt

+2

Désolé, mais ce n'est pas correct. Vérifiez le test (0) pour voir quand c'est différent. La raison en est que $ x == ($ x> 5) teste si $ x == vrai, ce qu'il évaluera comme vrai tant que $ x n'est pas 0. ... et maintenant mon commentaire semble mal placé comme vous enlevé "ils sont identiques". – MatsLindh

+0

Pour répondre à ma propre question ci-dessus, @fiskfisk fait un excellent point que '$ x == true' évalue à' true' parce que '6' est' truthy'. – Matt