为什么 PHP 给出意外的输出?

Why does PHP give unexpected output?

$i = 2;
$result = ($i == 2) ? "Two" : ($i == 1) ? "One" : "Other";

echo $result; // outputs: One

而 C# 中的相同代码输出:两个

int i=2;
String result = (i == 2) ? "Two" : (i == 1) ? "One" : "Other" ;
Console.Write( result ); // outputs: Two

计算三元运算符从左到右

($i == 2) ? "Two" : ($i == 1) ? "One" : "Other"
"Two" ? "One" : "Other"  // first part evaluated to "Two"
"One"                    // non-empty strings evaluate to true

所以你应该在输出中得到 One,而不是 Other。有点棘手。

来自 manual 的名言:

It is recommended that you avoid "stacking" ternary expressions. PHP's behaviour when using more than one ternary operator within a single statement is non-obvious.

@light 已经给出了解释,但是要得到你想要的结果你需要额外的大括号:

$i = 3;
$result = ($i == 2) ? "Two" : (($i == 1) ? "One" : "Other");
echo $result, PHP_EOL;

$i = 2;
$result = ($i == 2) ? "Two" : (($i == 1) ? "One" : "Other");
echo $result, PHP_EOL;

$i = 1;
$result = ($i == 2) ? "Two" : (($i == 1) ? "One" : "Other");
echo $result, PHP_EOL;

Demo

这是因为 C# 是强类型的,需要一个布尔值作为三元运算符的第一个参数,而 PHP 是松散类型的,基本上每个值都可以转换为其等效的布尔值。此外,三元运算符是从左到右求值的。这是什么意思?

在 C# 中,我们需要运算符最左边的布尔值,所以这个表达式:

String result = (i == 2) ? "Two" : (i == 1) ? "One" : "Other" ;

将按以下顺序进行评估:

String result = (i == 2) ? "Two" : ((i == 1) ? "One" : "Other");

i==2 等于 true 所以 "Two" 将被分配为最终结果。在 PHP 中,它看起来有点不同。我们可以解释这个表达式:

$result = ($i == 2) ? "Two" : ($i == 1) ? "One" : "Other";

像这样

$result = (($i == 2) ? "Two" : ($i == 1)) ? "One" : "Other";

$i 等于 2,因此值 "Two" 将是第一个表达式的结果。非空字符串值在 PHP 中等于 true,因此 "One" 将是最终结果。