三元或不三元?

我个人是三元运算符的提倡者:()? :; 我意识到它有它的位置,但是我遇到了许多完全反对使用它的程序员,而且有些使用它的频率太高。

你对它有什么感想? 你使用过什么有趣的代码?

用于简单expression式

 int a = (b > 10) ? c : d; 

不要链接或嵌套三元运营商,因为它很难阅读和混淆:

 int a = b > 10 ? c < 20 ? 50 : 80 : e == 2 ? 4 : 8; 

而且,在使用三元运算符时,请考虑以提高可读性的方式格式化代码:

 int a = (b > 10) ? some_value : another_value; 

由于不能在每个子expression式上放置断点,因此它会使debugging稍微困难一些。 我很less使用它。

我爱他们,特别是在types安全的语言。

我不明白这是怎么回事:

 int count = (condition) ? 1 : 0; 

比这更难:

 int count; if (condition) { count = 1; } else { count = 0; } 

编辑 –

我认为,三元运营商使一切都不那么复杂,比替代scheme更整齐。

三元?:运算符仅仅是程序性的构造函数。 所以只要你不使用嵌套的?:expression式,任何操作的函数表示的参数都适用于这里。 但是,嵌套三元操作可能会导致代码彻底混淆(练习读者:尝试编写一个parsing器来处理嵌套的三元条件,您将会体会到它们的复杂性)。

但有很多情况下,保守使用?:操作符会导致代码实际上比其他操作更容易阅读。 例如:

 int compareTo(Object object) { if((isLessThan(object) && reverseOrder) || (isGreaterThan(object) && !reverseOrder)) { return 1; if((isLessThan(object) && !reverseOrder) || (isGreaterThan(object) && reverseOrder)) { return -1; else return 0; } 

现在比较一下:

 int compareTo(Object object) { if(isLessThan(object)) return reverseOrder ? 1 : -1; else(isGreaterThan(object)) return reverseOrder ? -1 : 1; else return 0; } 

由于代码更紧凑,因此语法噪声更less,通过明智地使用三元运算符(这只与reverseOrder属性有关),最终结果并不特别简洁。

链接我很好 – 嵌套,不是很多。

我倾向于在C语言中更多地使用它们,因为它们是一个有价值的if语句,所以它减less了不必要的重复或variables:

 x = (y < 100) ? "dog" : (y < 150) ? "cat" : (y < 300) ? "bar" : "baz"; 

而不是

  if (y < 100) { x = "dog"; } else if (y < 150) { x = "cat"; } else if (y < 300) { x = "bar"; } else { x = "baz"; } 

在这样的任务中,我发现重构和清晰都不那么重要。

另一方面,当我在ruby工作时,我更可能使用, if...else...end因为它也是一个expression式。

 x = if (y < 100) then "dog" elif (y < 150) then "cat" elif (y < 300) then "bar" else "baz" end 

(不过,无可否认,对于这样简单的事情,我可能只是使用三元运算符)。

这是一个风格问题,真的; 我倾向于遵循的潜意识规则是:

  • 只评估1expression式 – 所以foo = (bar > baz) ? true : false foo = (bar > baz) ? true : false ,但不是foo = (bar > baz && lotto && someArray.Contains(someValue)) ? true : false foo = (bar > baz && lotto && someArray.Contains(someValue)) ? true : false
  • 如果我用它来显示逻辑,例如<%= (foo) ? "Yes" : "No" %> <%= (foo) ? "Yes" : "No" %>
  • 只有真正把它用于分配; 从来没有stream逻辑(所以从来没有(foo) ? FooIsTrue(foo) : FooIsALie(foo) 三元stream动逻辑本身就是一个谎言,忽略了最后一点。

我喜欢它,因为简单的赋值操作简洁而优雅。

像许多意见问题一样,答案是不可避免的: 这取决于

像这样的东西:

 return x ? "Yes" : "No"; 

我认为这我更简洁(而且我可以更快地parsing)

 if (x) { return "Yes"; } else { return "No"; } 

现在,如果你的条件expression式是复杂的,那么三元操作不是一个好的select。 就像是:

 x && y && z >= 10 && s.Length == 0 || !foo 

对三元运算符来说不是一个好的select。

顺便说一下,如果你是一个C程序员,GCC实际上有一个扩展 ,允许你排除三元组的if-true部分,如下所示:

 /* 'y' is a char * */ const char *x = y ? : "Not set"; 

假设y不是NULL它将把x设置为y 。 好东西。

在我看来,只有在需要expression式的情况下使用三元运算符才有意义。

在其他情况下,似乎三元运算符会降低清晰度。

通过圈复杂度的衡量, if语句或三元运算符的使用是等价的。 那么这个答案是否定的 ,复杂性就和以前一样了。

通过诸如可读性,可维护性和DRY(不重复自己)等其他方法,任何一种select都可能比另一种更好。

我经常在我被约束在构造函数中工作的地方(例如,新的.NET 3.5 LINQ to XML结构)中使用它,以在可选参数为null时定义默认值。

被举的例子:

 var e = new XElement("Something", param == null ? new XElement("Value", "Default") : new XElement("Value", param.ToString()) ); 

或(谢天谢地)

 var e = new XElement("Something", new XElement("Value", param == null ? "Default" : param.ToString() ) ); 

不pipe你是否使用三元运算符,确保你的代码是可读的是重要的。 任何构造都可以变得不可读。

我尽可能使用三元运算符,除非它使得代码非常难以阅读,但是这通常只是表示我的代码可能会使用一些重构。

它总是令我困惑,有些人认为三元运算符是一个“隐藏”的特征,或者有点神秘。 这是我开始用C语言编程学到的第一件事情,我不认为它会降低可读性。 这是语言的自然部分。

我同意jmulder:它不应该被用来代替if ,而是它有其expression的地方或者expression式:

 echo "Result: " + n + " meter" + (n != 1 ? "s" : ""); return a == null ? "null" : a; 

前者只是一个例子,应该使用更好的i18n复数支持!

如果你使用三元运算符进行简单的条件赋值,我认为没关系。 我已经看到它(ab)用来控制程序stream程,甚至没有做任务,我认为这应该避免。 在这些情况下使用if语句。

(黑客的一天)

 #define IF(x) x ? #define ELSE : 

那么你可以做if-then-else作为expression式:

 int b = IF(condition1) res1 ELSE IF(condition2) res2 ELSE IF(conditions3) res3 ELSE res4; 

我认为应该在需要时使用三元运算符。 这显然是一个非常主观的select,但我发现一个简单的expression式(特别是作为一个返回expression式)比一个完整的testing更加清晰。 C / C ++中的示例:

 return (a>0)?a:0; 

相比:

 if(a>0) return a; else return 0; 

您也有解决scheme之间的三元运算符和创build一个函数的情况。 例如在Python中:

 l = [ i if i > 0 else 0 for i in lst ] 

替代scheme是:

 def cap(value): if value > 0: return value return 0 l = [ cap(i) for i in lst ] 

在Python中(例如)需要足够的时间,这样一个成语可以定期看到:

 l = [ ((i>0 and [i]) or [0])[0] for i in lst ] 

这一行使用Python中逻辑运算符的属性:它们是懒惰的,如果它等于最终状态,则返回最后计算的值。

我喜欢他们。 我不知道为什么,但是当我使用三元expression时,我感觉非常酷。

我曾经见过这样的野兽(实际上这更糟,因为它是isValidDate,并且每天都检查一次,但是我不能为了记住整个事情而烦恼):

 isLeapYear = ((yyyy % 400) == 0) ? 1 : ((yyyy % 100) == 0) ? 0 : ((yyyy % 4) == 0) ? 1 : 0; 

显然,一系列if语句本来会更好(虽然这个比我曾经看到的macros观版本还要好)。

我不介意这样的小事情,如:

 reportedAge = (isFemale && (Age >= 21)) ? 21 + (Age - 21) / 3 : Age; 

甚至有点棘手的事情,如:

 printf ("Deleted %d file%s\n", n, (n == 1) ? "" : "s"); 

我喜欢在debugging代码中使用操作符来打印错误值,所以我不必一直查找它们。 通常我这样做的debugging打印,不会保持一旦我完成开发。

 int result = do_something(); if( result != 0 ) { debug_printf("Error while doing something, code %x (%s)\n", result, result == 7 ? "ERROR_YES" : result == 8 ? "ERROR_NO" : result == 9 ? "ERROR_FILE_NOT_FOUND" : "Unknown"); } 

我几乎从不使用三元运算符,因为每当我使用它时,总会让我想到比以后更多的时候,当我尝试维护它时。

我喜欢避免冗长,但是当它让代码更容易拾取时,我会去详细search。

考虑:

 String name = firstName; if (middleName != null) { name += " " + middleName; } name += " " + lastName; 

现在,这有点冗长,但是我发现它比以下更具可读性:

 String name = firstName + (middleName == null ? "" : " " + middleName) + " " + lastName; 

要么:

 String name = firstName; name += (middleName == null ? "" : " " + middleName); name += " " + lastName; 

它似乎太多的信息压缩太less的空间,没有明确发生了什么事情。 每次我看到三元操作符被使用,我总是发现一个看起来更容易阅读的替代方法…然后再一次,这是一个非常主观的观点,所以如果你和你的同事发现三元非常可读,就去做吧。

那么,它的语法是可怕的。 我发现函数ifs非常有用,并且经常使代码更具可读性。

我会build议制作一个macros,使其更具可读性,但我敢肯定,有人可以拿出一个可怕的边缘案例(因为总是有CPP)。

只有当:

$ var =(simple> test?simple_result_1:simple_result_2);

吻。

正如其他人所指出的那样,他们对简单的条件很好。 我特别喜欢他们的默认值(类似于|| JavaScript和Python中的用法),例如

 int repCount = pRepCountIn ? *pRepCountIn : defaultRepCount; 

另一个常见用法是在C ++中初始化一个引用。 由于引用必须在相同的语句中声明和初始化,所以不能使用if语句。

 SomeType& ref = pInput ? *pInput : somethingElse; 

我把三元运营商很像GOTO。 他们有自己的位置,但是他们通常应该避免让代码更容易理解。

我最近看到了三元运算符的变体(好,有点),使得标准“()”:“变体似乎是一个清晰的典范:

 var Result = [CaseIfFalse, CaseIfTrue][(boolean expression)] 

或者,举一个更具体的例子:

 var Name = ['Jane', 'John'][Gender == 'm']; 

请注意,这是Javascript,所以在其他语言中可能无法使用(谢天谢地)。

对于简单的情况,我喜欢使用它。 实际上,读取/编码例如作为函数的参数或类似的东西要容易得多。 此外,为了避免新的路线,我喜欢保持我所有的if / else。

在我的书中,这将是一个很大的“不”。

所以,恢复一个单一的if / else我将使用三元运算符。 对于其他情况,常规的if / else if / else(或switch)

我通常使用这样的东西:

 before: if(isheader) drawtext(x,y,WHITE,string); else drawtext(x,y,BLUE,string); after: drawtext(x,y,isheader==true?WHITE:BLUE,string); 

我喜欢Groovy三元运算符的特例,称为Elvis运算符:?:

 expr ?: default 

如果它不为null,则此代码评估为expr,如果是,则为默认值。 从技术上讲,它不是一个真正的三元运算符,但它确实与它有关,并节省了大量的时间/打字。

对于简单的任务,如根据条件分配不同的值,他们是伟大的。 根据条件不同,我不会使用它们。

有这么多的答案, 这取决于 。 我发现,如果在快速扫描代码时三元比较不可见,则不应使用它。

作为一个侧面的问题,我也可能会注意到,它的存在实际上是一个倒退,因为在C中,比较testing是一个陈述。 在Icon中, if结构(就像图标的大部分)实际上是一个expression式。 所以你可以做这样的事情:

 x[if y > 5 then 5 else y] := "Y" 

…我发现比ternery比较运算符更可读。 🙂

最近有一个关于将?:运算符添加到Icon的可能性的讨论,但是有几个人正确地指出, if工作的if ,完全没有必要。

这意味着如果你可以用C语言(或其他任何有ternery操作符的语言)来做到这一点,那么事实上根本就不需要ternery操作符。

如果你和你的同事们明白他们做了什么,而他们又不是以大批人创build的,我认为他们让代码更加复杂,更容易阅读,因为代码less了。

唯一一次我认为三元运算符使代码更难理解的是当你在一行中有3或4以上的时候。 大多数人不记得他们是正确的优先顺序,当你有一堆他们是阅读代码的噩梦。