C#中的三元运算符关联性 - 我可以依赖它吗?

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).最后的例子]

  • 关于可读性的说明.任何具有函数式编程背景的人都会立即认识到这一点(它看起来几乎就像Haskell的具有适当格式的保护条款).因此,尽管它可能不是普遍接受和可用的,但它在某些圈子中肯定是*惯用的,并且在某些项目中可能非常合适.从更个人的角度来看,*我*在个人项目中使用它,我发现它*比链接`更多可读性如果`,如果你不能阅读它,那么就离开我的代码. (4认同)
  • @Mark:是的,但PHP很糟糕.我已经过了关怀点了. (2认同)
  • @Juan 什么,我应该写 PHP 很糟糕?这似乎有点题外话。这并不是很有趣……每个人都知道*这一点*。 (2认同)

小智 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

  • 绝对同意.如果你不得不问,那就不清楚了.如果不清楚,那么在它周围加上f-ing括号并停止成为一个聪明的程序员.这就是最糟糕的错误来自哪里. (4认同)