三元运算符既是左操作符又是右操作符..或两者都不是
Posted
技术标签:
【中文标题】三元运算符既是左操作符又是右操作符..或两者都不是【英文标题】:Ternary operator as both left operative and right operative.. or neither 【发布时间】:2016-02-29 13:46:49 【问题描述】:问题是:如果您对这个问题很清楚,请向我解释我没有看到什么。我的问题是:三元实际上是如何工作的?澄清我的问题:从右到左的关联性在这里真正意味着什么?为什么关联性与评估顺序不同?这显然就像一个 if else 语句。它不是从右到左评估的。在我看来,它是从左到右关联的。
我做了布尔值来尝试证明这一点。它告诉我它不是右联想。(我可能不明白右联想是什么意思。)如果它是右联想,它会像这样工作,这是给我的答案:
“由于这个操作符是右结合的,你的代码就像;”
true ? false ? false ? false ? 3 : 4 : 5 : 6 : 7
evaluated as;
true ? false ? false ? (false ? 3 : 4) : 5 : 6 : 7
which evaluated as;
true ? false ? false ? 4 : 5 : 6 : 7
which evaluated as;
true ? false ? (false ? 4 : 5) : 6 : 7
which evaluated as;
true ? false ? 5 : 6 : 7
which evaluated as;
true ? (false ? 5 : 6) : 7
which evaluated as;
true ? 6 : 7
which returns 6.
我试图证明这一点,像这样:
int Proof = ternaryTrueOne() ? ternaryTrueTwo() ? ternaryFalseOne() ?
ternaryTrueThree() ? ternaryFalseTwo() ? 2 : 3 : 4 : 5 : 6 : 7;
static bool ternaryTrueOne()
Console.WriteLine("This is ternaryTrueOne");
return true;
static bool ternaryTrueTwo()
Console.WriteLine("This is ternaryTrueTwo");
return true;
static bool ternaryTrueThree()
Console.WriteLine("This is ternaryTrueThree");
return true;
static bool ternaryFalseOne()
Console.WriteLine("This is ternaryFalse");
return false;
static bool ternaryFalseTwo()
Console.WriteLine("This is ternaryFalseTwo");
return false;
在这种情况下,这将以相同的方式进行评估。正确的?这意味着 ternaryfalsetwo 将首先写入控制台。但它没有。它根本不写。它实际上是这样工作的,并且我将三元表达式编写为 if 语句。它从左到右工作,并且不必评估其余代码。在第一个错误语句之后,所有其他语句都无法访问。
private static int Proof2()
if (ternaryTrueOne())
if (ternaryTrueTwo())
if (ternaryFalseOne())
if (ternaryTrueThree())
if (ternaryFalseTwo())
return 6;
else
return 7;
return 5;
else
return 6;
return 4;
else
return 5;
return 3;
else
return 4;
return 2;
else
return 3;
原来的答案错了吗?右关联性的真正含义是什么?
【问题讨论】:
&&, ||, ?, ??是 C# 中的快捷操作符。因此,当第一个参数评估为使表达式的其余部分无关紧要的值时,不必执行它。这在从左到右进行时效果更好(更容易理解最左边的参数何时是第一个参数)。 【参考方案1】:由于三元条件运算符在运算符优先级表中具有自己的位置(即没有其他运算符具有与它完全相同的优先级),因此关联规则仅适用于消除条件运算符与另一个条件运算符的歧义。
从右到左的关联性意味着隐式括号在最右边的三元组周围。
也就是说,
a ? b : c ? d : e
等价于
a ? b : (c ? d : e)
.
https://en.wikipedia.org/wiki/Operator_associativity 是一个有用的链接。
【讨论】:
我感觉自己迷失了方向。ternaryFalseTwo() ? 2 : 3
不应该是一部分,这就是为什么ternaryFalseTwo()
首先评估,这就是为什么它应该在顶部打印This is ternaryFalseTwo
?【参考方案2】:
关联性和执行顺序是相关的,但并不完全相同。
无论执行如何,关联性都存在 - 它是在数学中定义的,它完全由纯函数组成,因此“执行顺序”与结果无关。
C#中三元运算符的执行顺序非常简单:
-
评估条件
如果条件为真,则评估 trueBranch,如果条件为假,则评估 falseBranch
您可以将关联规则想象为“括号属于哪里”。
考虑一下:
a ? b : c ? d : e
如果我们对关联性的工作原理一无所知,我们可以看到放置括号的不同方式:
(a ? b : c) ? d : e 一个? b : (c ? d : e)第一种是左结合,第二种是右结合
不难看出这两种方法会导致不同的结果。例如,
(true ? true : false) ? false : false // false
true ? true : (false ? false : false) // true
现在,如果你在单独的 if
语句中重写它(这通常 不是三元组实际执行的方式,但它会这样做),你会得到:
if (a)
return b;
else
if (c) return d;
else return e;
评估与简单三元相同:
-
评估条件
a
如果为真,评估并返回b
;否则继续
评估条件c
如果为真,则评估并返回d
;否则评估并返回e
这应该使关联性和执行顺序的工作原理变得显而易见。这样我们就可以结束行程,并解释你的示例。
我们有一系列嵌套条件:
a ? b ? c ? 0 : 1 : 2 : 3
在这里如何应用关联性?它没有。这里没有关联操作!你正在做的是:
a ? (b ? (c ? 0 : 1) : 2) : 3
没有其他方法可以放置括号 - 这是解析运算符的唯一可能方法。
由于三元运算符是,嗯,三元,这有点难看,但是当你将它重写为函数时会变得更加明显(例如“非内联运算符”):
var f = (a, b, c) => a ? b : c;
f(a, f(b, f(c, 0, 1), 2), 3);
没有歧义 - 没有其他方法可以解析这个表达式。
用二元运算符显示关联性有点简单,所以考虑一下这种情况:
a - b - c
如果您不知道-
的关联性,您可以看到两种放置parens 的替代方式-(a - b) - c
和a - (b - c)
,这可以给您两种不同的结果。因此,-
是不关联的。
与+
相比,后者是(“完全”)关联的 - (a + b) + c
和 a + (b + c)
完全相同。
【讨论】:
(a + b) + c 和 a + (b + c) 完全一样 Not always :) @SonerGönül 我原本也想解释这一点(“数学中完全一样的东西”),但决定不这样做。为我服务:P 但就操作员的关联性而言,它们是同一回事。只是在 C# 中,+
并不总是完全关联:D以上是关于三元运算符既是左操作符又是右操作符..或两者都不是的主要内容,如果未能解决你的问题,请参考以下文章