true ? true : true ? false : false
对于那些现在完全感到困惑的人,我可以告诉你,这评估为 true 。换句话说,它等同于:
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)
简明扼要。但它确实取决于三元运算符的相关性,就像第一种情况一样。括号只会使意大利面条脱离它。
那么 - 这是指定的吗?我找不到了。
答案 0 :(得分:22)
是的,您可以依赖于此(不仅在C#中,而且在所有(我知道)其他语言(except PHP ... go figure)中使用条件运算符)并且您的用例实际上是非常常见的虽然有些人厌恶它,但仍然在练习。
ECMA-334(C#标准)中的相关部分是14.13§3:
条件运算符是右关联的,这意味着操作从右到左分组。 [示例:表单
a ? b : c ? d : e
的表达式计算为a ? b : (c ? d : e)
。结束 例子]
答案 1 :(得分:17)
如果你不得不问,不要。阅读代码的任何人都必须经历您所做的相同过程,一遍又一遍,任何需要查看代码的时间。调试这样的代码并不好玩。最终它只会被改为使用括号。
Re:“尝试用括号写下整个事情。”
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。
最后一点要思考,如果你的一些代码看起来很聪明:
调试是第一次编写代码的两倍。因此,如果您尽可能巧妙地编写代码,那么根据定义,您不够聪明,无法对其进行调试。 - Brian W. Kernighan
答案 2 :(得分:4)
括号中有损于代码可读性的断言是错误的假设。我发现括号表达式更清晰。就个人而言,我会使用括号和/或重新格式化几行来提高可读性。重新格式化多行并使用缩进甚至可以消除对括号的需要。而且,是的,你可以依赖于这样一个事实,即关联的顺序是确定性的,从右到左。这允许表达式以预期的方式从左到右进行评估。
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);
答案 3 :(得分:1)
参考msdn: http://msdn.microsoft.com/en-us/library/ty67wk28%28VS.80%29.aspx
“如果condition为true,则计算第一个表达式并成为结果;如果为false,则计算第二个表达式并成为结果。只评估两个表达式中的一个。”
答案 4 :(得分:1)
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友情提供的链接上,用一个例子表示为“条件运算符是右关联的”。并且,正如您所建议的那样,我和其他人一致同意,您可以依赖它的事实允许更清晰的代码。