啊,你不就是喜欢三元虐待吗?:) 考虑以下表达式:

true ? true : true ? false : false

对于那些现在完全困惑的人,我可以告诉你,这评估为 真的. 。换句话说,它相当于:

true ? true : (true ? false : false)

但这可靠吗?我可以确定在某些情况下不会出现这样的情况:

(true ? true : true) ? false : false

有些人也许会说 - 好吧,只需添加括号即可,或者完全不要使用它 - 毕竟,众所周知,三元运算符是邪恶的!

当然是这样,但在某些情况下它们确实有意义。对于好奇的人 - 我正在编写通过一系列属性比较两个对象的代码。如果我冷写成这样就太好了:

obj1.Prop1 != obj2.Prop1 ? obj1.Prop1.CompareTo(obj2.Prop1) :
obj1.Prop2 != obj2.Prop2 ? obj1.Prop2.CompareTo(obj2.Prop2) :
obj1.Prop3 != obj2.Prop3 ? obj1.Prop3.CompareTo(obj2.Prop3) :
obj1.Prop4.CompareTo(obj2.Prop4)

清晰简洁。但它确实取决于三元运算符结合性,就像第一种情况一样工作。括号只会把它做成意大利面条。

那么 - 这是在任何地方指定的吗?我找不到它。

有帮助吗?

解决方案

是的,你可以靠这个(不只是在C#中,但在所有(我知道)其他语言(的除了PHP ...去图)与有条件运营商)和您的用例其实是一个相当普遍的做法虽然有些人痛恨它。

在ECMA-334(该C#标准)相关的部分是14.13§3:

  

条件运算符是右结合,这意味着操作从右到左进行分组。   [实施例:形式a ? b : c ? d : e的表达式被评估为a ? b : (c ? d : e)。结束   示例]

其他提示

如果你一定要问,那就不要问。任何阅读你的代码的人都必须一遍又一遍地经历与你相同的过程, 任何 需要查看代码的时间。调试这样的代码并不有趣。最终它只会被更改为使用括号。

关于: “尝试用括号写出整个内容。”

result = (obj1.Prop1 != obj2.Prop1 ? obj1.Prop1.CompareTo(obj2.Prop1) :
         (obj1.Prop2 != obj2.Prop2 ? obj1.Prop2.CompareTo(obj2.Prop2) :
         (obj1.Prop3 != obj2.Prop3 ? obj1.Prop3.CompareTo(obj2.Prop3) :
                                     obj1.Prop4.CompareTo(obj2.Prop4))))

澄清:

  • “如果 必须问,不问。”
  • “任何人读 你的 代码...”

遵循项目中常见的约定是保持一致性的方式,从而提高可读性。认为您可以编写每个人都可读的代码(包括那些甚至不懂该语言的人)的想法是愚蠢的!

然而,保持项目内的一致性是一个有用的目标,不遵循项目公认的惯例会导致争论,从而影响解决真正的问题。那些阅读您的代码的人应该了解项目中使用的常见和可接受的约定,甚至可能是直接从事该项目的其他人。如果他们不认识这些知识,那么他们应该学习这些知识,并且应该知道到哪里寻求帮助。

也就是说,如果在您的项目中使用不带括号的三元表达式是常见且可接受的约定,那么请务必使用它! 您必须提出的问题表明它在您的项目中不常见或不被接受。 如果您想更改项目中的约定,请执行明显明确的操作,将其标记为与其他项目成员讨论的内容,然后继续。这里这意味着使用括号或使用 if-else。

最后要思考的一点是,如果您的某些代码对您来说似乎很聪明:

调试的难度是最初编写代码的两倍。因此,如果您尽可能巧妙地编写代码,那么根据定义,您就不够聪明,无法调试它。— 布莱恩·W.克尼根

这括号从代码的可读性减损的断言是一个错误的假设。我发现括号表达更加清晰。就个人而言,我会用括号和/或重新格式化了几行以提高可读性。重新格式化了几行,并使用缩进甚至可以消除对括号的需要。而且,是的,你可以依靠的事实,联想的顺序是确定性的,从右到左。这允许表达,以评估从左至右以预期的方式。

obj1.Prop1 != obj2.Prop1
     ? obj1.Prop1.CompareTo(obj2.Prop1)
     : obj1.Prop2 != obj2.Prop2
           ? obj1.Prop2.CompareTo(obj2.Prop2)
           : obj1.Prop3 != obj2.Prop3
                  ? obj1.Prop3.CompareTo(obj2.Prop3)
                  : obj1.Prop4.CompareTo(obj2.Prop4);

参考MSDN: http://msdn.microsoft.com/en-我们/库/ ty67wk28%28VS.80%29.aspx

“如果条件为真,第一表达式进行求值,并成为结果;如果否,第二个表达式求值并变为结果只有两个表达式的要求不断评估的一个”

x = cond1 ? result1
  : cond2 ? result2
  : cond3 ? result3
  : defaultResult;

VS

if (cond1) x = result1;
else if (cond2) x = result2;
else if (cond3) x = result3;
else x = defaultResult;

我喜欢的第一个。

是的,你可以依靠条件运算符关联性。其使用手册中,在由DCP友情提供的链接,表述为“条件运算符是右结合”,用一个例子。而且,如你所说,我和大家都同意了,但事实上,你可以依靠它允许更清晰的代码。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top