Vil*_*lx- 17 .net c# ternary-operator associativity
啊,你不喜欢一个好的三元滥用吗?:)考虑以下表达式:
true ? true : true ? false : false
Run Code Online (Sandbox Code Playgroud)
对于那些现在完全感到困惑的人,我可以告诉你,这个评估是真的.换句话说,它等同于:
true ? true : (true ? false : false)
Run Code Online (Sandbox Code Playgroud)
但这可靠吗?我能否确定在某些情况下不会出现这种情况:
(true ? true : true) ? false : false
Run Code Online (Sandbox Code Playgroud)
有些人可能会说 - 好吧,只需添加括号或完全不使用它 - 毕竟,众所周知,三元运算符是邪恶的!
当然它们是,但在某些情况下它们确实有意义.对于好奇的 - 我正在拧干通过一系列属性比较两个对象的代码.如果我像这样冷写它会很好:
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)
Run Code Online (Sandbox Code Playgroud)
简洁明了.但它确实取决于三元运算符的相关性,就像第一种情况一样.括号只会使意大利面条脱离它.
那么 - 这是指定的吗?我找不到它.
Kon*_*lph 22
是的,您可以依赖于此(不仅在C#中,而且在所有(我知道)其他语言(除了PHP ...去图)与条件运算符)并且您的用例实际上是一种非常常见的做法,尽管有些人厌恶它.
ECMA-334(C#标准)中的相关部分是14.13§3:
条件运算符是右关联的,这意味着操作从右到左分组.[示例:表单的表达式
a ? b : c ? d : e计算为a ? b : (c ? d : e).最后的例子]
小智 17
如果你不得不问,不要.任何人阅读你的代码将不得不经过你做了同样的过程,一遍又一遍,任何需要在来看待该代码的时间.调试这样的代码并不好玩.最终它只会被改为使用括号.
回复: "尝试用括号写下整个事情."
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))))
Run Code Online (Sandbox Code Playgroud)
澄清:
遵循项目中常见的约定是如何保持一致性,从而提高可读性.认为你可以编写每个人都可读的代码 - 包括那些甚至不懂语言的人 - 这是一个愚蠢的错误!
但是,保持项目的一致性是一个有用的目标,并且不遵循项目的公认惯例会导致辩论减少解决实际问题.那些阅读代码的人应该知道项目中使用的常见和接受的约定,甚至可能是直接在其上工作的其他人.如果他们不了解他们,那么他们应该学习它们,并且应该知道在哪里寻求帮助.
也就是说 - 如果使用没有括号的三元表达式是项目中常见且被接受的约定,那么一定要使用它! 您必须要求表明它在您的项目中不常见或被接受. 如果你想改变你的项目中的约定,那么明确地明确无误,将其标记为与其他项目成员讨论的内容,然后继续.这意味着使用括号或使用if-else.
最后一点要思考,如果你的一些代码看起来很聪明:
调试的难度是首先编写代码的两倍.因此,如果您尽可能巧妙地编写代码,那么根据定义,您不够聪明,无法对其进行调试. - Brian W. Kernighan