三元运算符既是左运算符又是右运算符..或者两者都不是
Ternary operator as both left operative and right operative.. or neither
问题是:如果您清楚这个问题,请向我解释我没有看到的内容。我的问题是:三元实际上是如何工作的?澄清我的问题:从右到左的结合性在这里到底意味着什么?为什么结合性与评估顺序不同?这显然就像一个 if else 语句。它不是从右到左计算的。在我看来是从左到右联想。
我做了布尔值来尝试证明这一点。它告诉我它不是右联想。(我可能不明白右联想是什么意思。)如果它是右联想,它会这样工作,这是给我的答案:
"Since this operator is right-associative, your code works as;"
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;
}
}
原来的答案有错吗?右结合律的真正含义是什么?
由于三元条件运算符在运算符优先级中有自己的位置 table,(即没有其他运算符具有与它完全相同的优先级),关联性规则仅在消除条件运算符与另一个条件运算符的歧义时适用.
从右到左的结合性意味着隐式括号位于最右边的三元组周围。
即
a ? b : c ? d : e
相当于
a ? b : (c ? d : e)
.
https://en.wikipedia.org/wiki/Operator_associativity 是有用的 link.
关联性和执行顺序相关,但不完全相同。
关联性与任何执行无关 - 它在数学中定义,它完全由纯函数构成,因此 "order of execution" 与结果无关。
C#中三元运算符的执行顺序非常简单:
- 评估条件
- 如果条件为真则计算 trueBranch,如果条件为假则计算 falseBranch
您可以将关联性规则想象为 "where do the parens belong"。
考虑一下:
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
- 如果为真,求值 return
b
;否则继续
- 评估条件
c
- 如果为真,求值 return
d
;否则评估和 return e
这应该可以清楚地说明关联性和执行顺序是如何工作的。这样我们就可以结束旅程了,并解释一下你的例子。
我们有一系列嵌套条件:
a ? b ? c ? 0 : 1 : 2 : 3
这里如何应用结合律? 不会。这里没有关联操作!你正在做的是:
a ? (b ? (c ? 0 : 1) : 2) : 3
没有其他放置括号的方法 - 这是解析运算符的唯一可能方法。
由于三元运算符是三元运算符,所以这有点难看,但是当您将其重写为函数时它会变得更加明显(例如 "non-inline operator"):
var f = (a, b, c) => a ? b : c;
f(a, f(b, f(c, 0, 1), 2), 3);
没有歧义 - 没有其他方法可以解析此表达式。
用二元运算符显示结合性要简单一些,所以考虑这个场景:
a - b - c
如果你不知道 -
的结合性,你可以看到两种放置括号的替代方法 - (a - b) - c
和 a - (b - c)
,这可以给你两种不同的结果。因此,-
是 非 关联。
与 +
相比,它是 ("fully") 关联的 - (a + b) + c
和 a + (b + c)
完全相同。
问题是:如果您清楚这个问题,请向我解释我没有看到的内容。我的问题是:三元实际上是如何工作的?澄清我的问题:从右到左的结合性在这里到底意味着什么?为什么结合性与评估顺序不同?这显然就像一个 if else 语句。它不是从右到左计算的。在我看来是从左到右联想。
我做了布尔值来尝试证明这一点。它告诉我它不是右联想。(我可能不明白右联想是什么意思。)如果它是右联想,它会这样工作,这是给我的答案:
"Since this operator is right-associative, your code works as;"
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;
}
}
原来的答案有错吗?右结合律的真正含义是什么?
由于三元条件运算符在运算符优先级中有自己的位置 table,(即没有其他运算符具有与它完全相同的优先级),关联性规则仅在消除条件运算符与另一个条件运算符的歧义时适用.
从右到左的结合性意味着隐式括号位于最右边的三元组周围。
即
a ? b : c ? d : e
相当于
a ? b : (c ? d : e)
.
https://en.wikipedia.org/wiki/Operator_associativity 是有用的 link.
关联性和执行顺序相关,但不完全相同。
关联性与任何执行无关 - 它在数学中定义,它完全由纯函数构成,因此 "order of execution" 与结果无关。
C#中三元运算符的执行顺序非常简单:
- 评估条件
- 如果条件为真则计算 trueBranch,如果条件为假则计算 falseBranch
您可以将关联性规则想象为 "where do the parens belong"。
考虑一下:
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
- 如果为真,求值 return
b
;否则继续 - 评估条件
c
- 如果为真,求值 return
d
;否则评估和 returne
这应该可以清楚地说明关联性和执行顺序是如何工作的。这样我们就可以结束旅程了,并解释一下你的例子。
我们有一系列嵌套条件:
a ? b ? c ? 0 : 1 : 2 : 3
这里如何应用结合律? 不会。这里没有关联操作!你正在做的是:
a ? (b ? (c ? 0 : 1) : 2) : 3
没有其他放置括号的方法 - 这是解析运算符的唯一可能方法。
由于三元运算符是三元运算符,所以这有点难看,但是当您将其重写为函数时它会变得更加明显(例如 "non-inline operator"):
var f = (a, b, c) => a ? b : c;
f(a, f(b, f(c, 0, 1), 2), 3);
没有歧义 - 没有其他方法可以解析此表达式。
用二元运算符显示结合性要简单一些,所以考虑这个场景:
a - b - c
如果你不知道 -
的结合性,你可以看到两种放置括号的替代方法 - (a - b) - c
和 a - (b - c)
,这可以给你两种不同的结果。因此,-
是 非 关联。
与 +
相比,它是 ("fully") 关联的 - (a + b) + c
和 a + (b + c)
完全相同。