2010-08-03 9 views
14

Duplicate possible:
is “else if” faster than “switch() case” ?"si" par rapport à "switch"

J'ai rencontré beaucoup de situations ces derniers temps où j'ai conditionals très simple et besoin de branche flux d'application. Les « simples » moyens d'accomplir ce que je fais est juste une déclaration ancienne if/elseif simple:

if($value == "foo") { 
    // ... 
} elseif($value == "bar") { 
    // ... 
} elseif($value == "asdf" || $value == "qwerty") { 
    // ... 
} 

... mais je considère quelque chose comme aussi:

switch($value) { 
    case "foo": 
     // ... 
     break; 
    case "bar": 
     // ... 
     break; 
    case "qwer": 
    case "asdf": 
     // ... 
} 

Cela semble un peu moins lisible, mais peut-être c'est plus performant? Cependant, quand il y a de plus en plus « ou » expressions du conditionnel, il semble que l'instruction switch est beaucoup plus lisible et utile:

switch($value) { 
    case "foo": 
     // ... 
     break; 
    case "bar": 
    case "baz": 
    case "sup": 
     // ... 
     break; 
    case "abc": 
    case "def": 
    case "ghi": 
     // ... 
     break; 
    case "qwer": 
    case "asdf": 
     // ... 
} 

J'ai aussi vu des options où le débit de code est ramifié en utilisant des tableaux et fonctions:

function branch_xyz() {/* ... */} 
function branch_abc() {/* ... */} 
function branch_def() {/* ... */} 

$branches = array(
    "xyz"=>"branch_xyz", 
    "abc"=>"branch_abc", 
    "def"=>"branch_def" 
); 
if(isset($branches[$value])) { 
    $fname = $branches[$value]; 
    $fname(); 
} 

Cette dernière option a aussi sans doute l'avantage d'être distribuable dans plusieurs fichiers, mais il est assez laid.

Selon vous, quels sont les avantages les plus avantageux en termes de performances, de lisibilité et de facilité d'utilisation?

+1

utilisant la méthode 'switch' est mieux dans le genre de situation que vous avez spécifié. – Sarfraz

+2

Les performances ne tiennent même pas vraiment compte de cela. Ecrire le code lisible d'abord, puis profil et optimiser si nécessaire par la suite. –

+0

Dupliquer d'un doublon, etc. http://stackoverflow.com/questions/3387758/java-case-statment-or-if-statement-efficiency-perspective –

Répondre

27

Personnellement, je trouve le commutateur beaucoup plus lisible. Voici la raison:

if ($foo == 'bar') { 
} elseif ($foo == 'baz') { 
} elseif ($foo == 'buz') { 
} elseif ($fou == 'haz') { 
} 

Condensed comme ça, vous pouvez facilement voir le haut de voyage (que ce soit une faute de frappe, ou une différence honnête). Mais avec un interrupteur, vous savez implicitement ce que l'on voulait dire:

switch ($foo) { 
    case 'bar': 
     break; 
    case 'baz': 
     break; 
    case 'buz': 
     break; 
    case 'haz': 
     break; 
} 

Plus, qui est plus facile à lire:

if ($foo == 'bar' || $foo == 'baz' || $foo == 'bat' || $foo == 'buz') { 
} 

ou

case 'bar': 
case 'baz': 
case 'bat': 
case 'buz': 
    break; 

Du point de vue de la performance ... Eh bien , ne vous inquiétez pas de la performance. Sauf si vous en faites quelques milliers à l'intérieur d'une boucle serrée, vous ne serez même pas en mesure de faire la différence (la différence sera probablement dans la fourchette micro-seconde, sinon plus faible).

Optez pour la méthode que vous trouvez la plus lisible. C'est la partie importante. N'essayez pas de micro-optimiser. Souvenez-vous, ...

+1

Veillez à ce que le commutateur vous donne ** false ** négatifs et faux positifs en raison de [comparaison lâche] (http://stackoverflow.com/q/3525614/632951). Ici, 'switch' est une odeur de code et un fléau de sécurité ipso facto. Utilisez plutôt les clés de tableau. – Pacerier

+0

@Pacerier, pourquoi basculer est un fléau de sécurité? –

+3

@ ryabenko-pro, La comparaison lâche vous donnera des bugs subtils: 'switch (0) {case null: echo 'null'; Pause; par défaut: echo 'not null';} ' – Pacerier

1

Commutateur dit aux lecteurs plus tard que vous branchez basé sur la valeur d'une seule valeur, qu'ils devraient impliquer autrement en regardant toutes les conditions. Donc, je préférerais le commutateur pour la clarté

44

Je sais, la micro-optimisation est mauvaise.Mais curieux comme je suis, je l'ai fait un peu de référence en utilisant ce script:

<?php 
$numof = 100000; 
$file = fopen('benchmark.php', 'w'); 
if (!$file) die('file error'); 
fwrite($file, '<pre><?php' . "\n" . 'echo $i = $_GET[\'i\'], "\n";' . "\n"); 

fwrite($file, 
'$start = microtime(true); 
if ($i == 0) {}' . "\n"); 
for ($i = 1; $i < $numof; ++$i) { 
    fwrite($file, 'elseif($i == '.$i.') {}'. "\n"); 
} 
fwrite($file, 
'echo \'elseif took: \', microtime(true) - $start, "\n";' . "\n"); 

fwrite($file, 
'$start = microtime(true); 
switch($i) {' . "\n"); 
for ($i = 1; $i < $numof; ++$i) { 
    fwrite($file, 'case '.$i.': break;'. "\n"); 
} 
fwrite($file, 
'} 
echo \'switch took: \', microtime(true) - $start, "\n";' . "\n"); 

Les données résultantes (pour numof = 100000):

i: 0 
elseif took: 6.2942504882812E-5 
switch took: 3.504753112793E-5 

i: 10 
elseif took: 6.4849853515625E-5 
switch took: 4.3869018554688E-5 

i: 100 
elseif took: 0.00014805793762207 
switch took: 0.00011801719665527 

i: 1000 
elseif took: 0.00069785118103027 
switch took: 0.00098896026611328 

i: 10000 
elseif took: 0.0059938430786133 
switch took: 0.0074150562286377 

i: 100000 (first non-existing offset) 
elseif took: 0.043318033218384 
switch took: 0.075783014297485 

Avez-exécuter le script sur mon windows vieux et lent machine PHP 5.3.1 ou 5.3.2, ne sais pas juste.

+10

+1 pour faire quelque chose pour réellement essayer de mesurer la différence de performance pour donner une réponse valide à ce que la question demande. – Kmeixner

Questions connexes