是否应该使用三元运算符?

205

我个人是三元运算符的支持者:() ? :

我知道它有其适用场合,但我遇到过许多程序员完全反对使用它,还有一些程序员过于频繁地使用它。

你对此有何感觉?你见过哪些使用它的有趣代码?


9
当表达清晰明了时使用它,当它让人感到困惑时则避免使用。这是一个判断的问题。它可以使代码更易读,但仅适用于简单表达式。试图总是使用它与过度避免它一样有害。 - Abel
4
实际上,这是条件操作符。一个类似的问题在http://stackoverflow.com/questions/725973/what-do-fellow-net-developers-think-about-the-conditional-operator/726005上。 - Daniel Daranas
我有时会使用 x = x if x else y,但后来询问了别人的意见,得知它实际上可以简化为 x = x or y(http://stackoverflow.com/questions/18199381/self-referencing-ternary/18199562#18199562)。 - Scruffy
三元运算符可用于 if..else 结构无法使用的地方,例如在返回语句和函数参数中。虽然可以不使用三元运算符来实现相同的功能,但会导致代码变得更长,可执行文件变得更大。 - Arif Burhan
54个回答

10

我经常在一些只能使用构造函数的地方使用它 - 例如,新的.NET 3.5 LINQ到XML结构中 - 当一个可选参数为空时,定义默认值。

编造的例子:

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

或者(感谢 asterite)

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

无论是否使用三元运算符,确保您的代码可读性是最重要的。任何构造都可以变得难以阅读。


或者... var e = new XElement("Something", new XElement("value", param == null ? "默认值" : param.toString())); - asterite

8

我同意jmulder的观点:它不应该用来替代if,但在返回表达式或嵌入表达式中有其存在的意义:

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

前面只是一个例子,更好的使用复数的国际化和本地化支持!


6
如果您在进行简单条件赋值时使用三元运算符,我认为这是可以的。但我曾经看到它被(滥)用来控制程序流程而没有进行任何赋值,我认为应该避免这种情况。在这些情况下,请使用if语句。

6
今日技巧:
#define IF(x) x ?
#define ELSE :

然后你可以使用if-then-else作为表达式:

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

1
这不是回答问题的内容。 - Bruno Alexandre Rosa

5
我曾经见过这样的野兽(实际上更糟糕,因为它还验证了月份和日期,但我懒得记住整个东西):
isLeapYear =
    ((yyyy % 400) == 0)
    ? 1
    : ((yyyy % 100) == 0)
        ? 0
        : ((yyyy % 4) == 0)
            ? 1
            : 0;

在这里,明显地,一系列的if语句会更好(虽然这个版本仍然比我曾经看到的宏版本要好)。

对于像这样的小事情,我并不介意:

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

甚至包括稍微棘手的事情,比如:

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

你怎样说一系列的隔离条件语句更易读?我很好地阅读了你的“巨兽”代码。reportedAge是需要费点思考的示例——可能是因为它更像一个特例而不是像isThisYearALeapYear这样需要推敲的普遍情况。 - Axeman

5

我认为在需要的时候应该使用三目运算符。显然这是一个非常主观的选择,但是我发现一个简单的表达式(特别是作为返回表达式)比完整的测试更加清晰。例如在C/C++中:

return (a>0)?a:0;

与之相比:

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

有时候解决方案介于三元运算符和创建函数之间。例如在Python中:

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

替代方案是:
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中逻辑运算符的特性:它们是惰性的,并且如果最终状态等于最后计算的值,则返回该值。


4

我几乎从不使用三目运算符,因为每当我使用它时,稍后在尝试维护它时,它总是让我思考更多。

我喜欢避免冗长,但当它使代码更易于理解时,我会选择冗长。

考虑以下示例:

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;

它似乎将太多的信息压缩到太小的空间中,而不清楚正在发生什么。每次我看到三元运算符被使用时,我总是找到了一个更容易阅读的替代方案...但这只是一种非常主观的意见,如果您和您的同事发现三元运算符非常易读,请继续使用。


1
但那并不完全相同。在第二个例子中,您将所有三个语句压缩到一行中。这才是降低可读性的原因,而不是三元运算符。 - ilitirit
很好,我更新了以纳入你的评论,但对我来说,它仍然感觉杂乱无章...但再次强调,这是主观的...我并不是说三元运算符不可读,我只是说它对我来说不太可读(99%的时间)。 - Mike Stone

4

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


4

我喜欢在调试代码中使用运算符打印错误值,这样我就不必一直查找它们。通常,我会为那些在开发完成后不再保留的调试输出做这个操作。

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");
}

翻译如下:scnr: http://thedailywtf.com/Articles/What_Is_Truth_0x3f_.aspx - Meinersbur
在这种情况下,运算符优先级/短路是如何工作的? - Peter Mortensen

3

嗯,它的语法很可怕。我发现功能性的ifs非常有用,它们通常可以使代码更易读。

我建议制作一个宏来使其更易读,但我相信总会有一些可怕的边缘情况(就像C ++一样)。


许多BASIC实现和变体都有IF函数来代替三元运算符。我见过一些代码库中将其定义为C语言的宏。 - Sparr
嗯,我本来在考虑函数式编程语言,但是没错。 - Marcin
制作宏以使代码更易读,你真是个开玩笑的人! - niXar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接