[英]Ternary operator associativity in C# - can I rely on it?
啊,你不喜欢一个好的三元滥用吗? :)考虑以下表达式:
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
a ? b : c ? d : e
被评估为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。
最后一点要思考,如果你的一些代码看起来很聪明:
调试的难度是首先编写代码的两倍。 因此,如果您尽可能巧妙地编写代码,那么根据定义,您不够聪明,无法对其进行调试。 - Brian W. Kernighan
括号中有损于代码可读性的断言是错误的假设。 我发现括号表达式更清晰。 就个人而言,我会使用括号和/或重新格式化几行来提高可读性。 重新格式化多行并使用缩进甚至可以消除对括号的需要。 而且,是的,你可以依赖于这样一个事实,即关联的顺序是确定性的,从右到左。 这允许表达式以预期的方式从左到右进行评估。
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-us/library/ty67wk28%28VS.80%29.aspx
“如果condition为true,则计算第一个表达式并成为结果;如果为false,则计算第二个表达式并成为结果。只评估两个表达式中的一个。”
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 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.