我最近遇到很多情况,我的条件很简单,需要分支应用程序流程。完成我正在做的事情的“最简单”的方法只是一个简单的if
/ elseif
陈述:
if($value == "foo") {
// ...
} elseif($value == "bar") {
// ...
} elseif($value == "asdf" || $value == "qwerty") {
// ...
}
...但我也在考虑这样的事情:
switch($value) {
case "foo":
// ...
break;
case "bar":
// ...
break;
case "qwer":
case "asdf":
// ...
}
这似乎有点不太可读,但也许它的性能更高?但是,当条件中有越来越多的“或”表达式时,似乎switch语句更具可读性和实用性:
switch($value) {
case "foo":
// ...
break;
case "bar":
case "baz":
case "sup":
// ...
break;
case "abc":
case "def":
case "ghi":
// ...
break;
case "qwer":
case "asdf":
// ...
}
我还看到了使用数组和函数分支代码流的选项:
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();
}
最后一个选项也可能具有可在多个文件中分发的好处,尽管它非常难看。
在性能,可读性和易用性方面,您认为哪一方面最具优势?
答案 0 :(得分:45)
我知道,微优化很糟糕。但是我很好奇,我使用这个脚本做了一些基准测试:
<?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");
结果数据(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
使用PHP 5.3.1或5.3.2在旧的和慢速的Windows机器上运行脚本,dunno是对的。
答案 1 :(得分:27)
就个人而言,我发现交换机更具可读性。原因如下:
if ($foo == 'bar') {
} elseif ($foo == 'baz') {
} elseif ($foo == 'buz') {
} elseif ($fou == 'haz') {
}
像这样简单,你可以很容易地看到旅行(无论是拼写错误还是诚实的差异)。但是通过开关,您可以隐含地知道其含义:
switch ($foo) {
case 'bar':
break;
case 'baz':
break;
case 'buz':
break;
case 'haz':
break;
}
另外,这更容易阅读:
if ($foo == 'bar' || $foo == 'baz' || $foo == 'bat' || $foo == 'buz') {
}
或
case 'bar':
case 'baz':
case 'bat':
case 'buz':
break;
从性能角度来看......好吧,不要担心性能问题。除非你在一个紧密的循环中做了几千个,否则你甚至无法区分(差异可能在微秒范围内,如果不是更低)。
转到您认为最易读的方法。这是重要的部分。不要尝试微观优化。请记住,Premature Optimization Is The Root Of All Evil
...
答案 2 :(得分:3)
您应该考虑使用多态作为控制if或switch等结构的替代方法。如果你有很多选项,它会特别方便,因为它可以大大简化控制逻辑。
我在这里写了关于这个概念:http://codeutopia.net/blog/2009/02/02/avoiding-endless-switch-case-structures-with-classes/
答案 3 :(得分:1)
Switch告诉后来读者你根据单个值的值进行分支,否则他们必须通过查看所有条件来暗示这一点。所以我更喜欢开关的清晰度