5

问题是:如果您对这个问题很清楚,请向我解释我没有看到什么。我的问题是:三元实际上是如何工作的?澄清我的问题:从右到左的关联性在这里真正意味着什么?为什么关联性与评估顺序不同?这显然就像一个 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;
    }
}

原来的答案错了吗?正确的关联性到底意味着什么?

4

2 回答 2

5

由于三元条件运算符在运算符优先级表中有自己的位置(即没有其他运算符具有与其完全相同的优先级),因此关联规则仅适用于消除条件运算符与另一个条件运算符的歧义。

从右到左的关联性意味着隐式括号在最右边的三元组周围。

那是,

a ? b : c ? d : e

相当于

a ? b : (c ? d : e).

https://en.wikipedia.org/wiki/Operator_associativity是一个有用的链接。

于 2015-11-26T12:51:27.743 回答
4

关联性和执行顺序是相关的,但并不完全相同。

无论执行如何,关联性都存在 - 它是在数学中定义的,它完全由纯函数组成,因此“执行顺序”与结果无关。

C#中三元运算符的执行顺序非常简单:

  1. 评估条件
  2. 如果条件为真,则评估 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;
}

评估与简单三元相同:

  1. 评估条件a
  2. 如果为真,则评估并返回b;否则继续
  3. 评估条件c
  4. 如果为真,则评估并返回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

如果您不了解 的关联性-,您可以看到两种放置括号的替代方式 -(a - b) - ca - (b - c),这可以给您两种不同的结果。因此,不是-关联的。

+相比,它是(“完全”)关联的 -(a + b) + c并且a + (b + c)是完全相同的东西。

于 2015-11-26T13:01:13.137 回答