2010-07-22 200 views
93

有什么好处和弊端:运营商,而不是标准的if-else语句。最明显的莫过于:优点使用条件的:(三元)运算符

条件:?操作

  • 短,直接价值的比较处理和分配
  • 似乎并没有被作为的if/else灵活时更简洁构建

标准的if/else

  • 可以应用在更多的情况下(如函数调用)
  • 通常是不必要的长时间

可读性似乎每个取决于说法有所不同。在第一次接触到?:操作符之后的一段时间,我花了一些时间来消化它的工作原理。你会推荐尽可能使用它,或者坚持if/else,因为我与许多非程序员一起工作?

+8

你已经得到它的要点。 – 2010-07-22 19:51:23

+0

我只在C#中做了一点,但大多数语言都允许在条件运算符内部进行函数调用。C#真的不是吗?这似乎很奇怪...... – 2010-07-22 19:51:58

+1

@Nicholas Knight:我猜OP意味着你不能这样做,例如'SomeCheck()? DoFirstThing():DoSecondThing();' - 你必须使用表达式来返回一个值。 – 2010-07-22 19:53:06

回答

111

我基本上会建议使用它,只有当产生的说法是极短的,代表了简洁过的if/else相当于在不牺牲可读性显著上升。

很好的例子:

int result = Check() ? 1 : 0; 

错误的例子:

int result = FirstCheck() ? 1 : SecondCheck() ? 1 : ThirdCheck() ? 1 : 0; 
+5

好的调用,但对于记录,这是“简洁”。 – mquander 2010-07-22 19:59:04

+5

@mquander,你确定? http://www.merriam-webster.com/dictionary/concise – 2010-07-22 20:07:52

+1

嗯,去图;也许它也可以是。 – mquander 2010-07-22 20:11:02

10

我觉得特别有帮助做网站开发的时候,如果我要设置为在请求发送,如果它被定义,或者某些缺省值赋值的变量,如果它不是。

+3

在web dev中的+1默认值是一个很好的例子,使用三元运算符的好地方 – 2010-07-22 19:53:03

+1

在这种情况下,空合并运算符('??')将更加适合... – 2010-09-01 21:29:53

3

如果我设置的值,我知道这将永远是代码这样做一条线,我通常使用三元(条件)运算符。如果有机会,我的代码和逻辑将在未来发生变化,我使用if/else,因为其他程序员更清楚。

进一步您感兴趣的可能是?? operator

3

条件运算符的优点是它是一个运算符。换句话说,它返回一个值。由于if是一个声明,它不能返回一个值。

4

一件事使用三元运算符,它是一个表达式不是一个语句时承认。

在类似方案的函数式语言的区别并不存在:

(如果(> AB)AB)

条件:?操作 “似乎不那么灵活,因为if/else构造“

在函数式语言中它是。

当在命令式语言中编程时,我在通常使用表达式(赋值,条件语句等)的情况下应用三元运算符。

3

我建议限制使用三元(?:)运算符来简化单线赋值if/else逻辑。类似的东西这种模式:

if(<boolCondition>) { 
    <variable> = <value>; 
} 
else { 
    <variable> = <anotherValue>; 
} 

可以很容易地转换为:

<variable> = <boolCondition> ? <value> : <anotherValue>; 

我会避免使用三元运算符在需要的if/else的if/else,嵌套情况下的if/else,或者如果/ else分支逻辑导致多行评估。在这些情况下应用三元运算符可能会导致无法读取,令人困惑和无法管理的代码。希望这可以帮助。

5

条件运算符是非常适合短的条件下,这样的:

varA = boolB ? valC : valD; 

我用它偶尔,因为它需要较少的时间来写东西呀......不幸的是,这个分支有时可以通过另一个错过开发者浏览你的代码。另外,代码通常不是那么简短,所以我通常会通过将?和:在不同的行,像这样:

doSomeStuffToSomething(shouldSomethingBeDone() 
    ? getTheThingThatNeedsStuffDone() 
    : getTheOtherThingThatNeedsStuffDone()); 

但是,大的优势,使用if/else块(为什么我喜欢他们)是,它更容易以后进来,并添加一些额外的逻辑分支,

if (shouldSomethingBeDone()) { 
    doSomeStuffToSomething(getTheThingThatNeedsStuffDone()); 
    doSomeAdditionalStuff(); 
} else { 
doSomeStuffToSomething(getTheOtherThingThatNeedsStuffDone()); 
} 

或添加另一个条件:

if (shouldSomethingBeDone()) { 
    doSomeStuffToSomething(getTheThingThatNeedsStuffDone()); 
    doSomeAdditionalStuff(); 
} else if (shouldThisOtherThingBeDone()){ 
    doSomeStuffToSomething(getTheOtherThingThatNeedsStuffDone()); 
} 

那么,到底,它是关于(较短的使用?)方便您现在对方便你(及其他)以后。这是一个判断的呼吁......但和所有其他代码格式问题一样,唯一真正的规则是要保持一致,并且对于那些必须维护(或评级)代码的人来说,要有视觉上的礼貌。

(所有代码眼编译)

1

有使用的一些性能优势?运营商在例如。 MS Visual C++,但这是一个真正的编译器特定的事情。在某些情况下,编译器实际上可以优化条件分支。

1

我最发现自己使用它的情况是因拖欠值,特别是在回报

return someIndex < maxIndex ? someIndex : maxIndex; 

这些都是真的,我觉得它不错的唯一的地方,但对他们我做的。

但如果你正在寻找一个布尔值,这可能有时看起来像一个合适的事情:

bool hey = whatever < whatever_else ? true : false; 

因为它很容易阅读和理解,但这种想法应该总是扔了更显而易见的:

bool hey = (whatever < whatever_else); 
1

如果您需要在相同条件下多个分支,使用if:

if (A == 6) 
    f(1, 2, 3); 
else 
    f(4, 5, 6); 

如果需要使用不同的条件下多个分支机构,那么if语句计数将像滚雪球一样,你要使用的三元:

f((A == 6)? 1: 4, (B == 6)? 2: 5, (C == 6)? 3: 6); 

此外,还可以使用三元运算的初始化。

const int i = (A == 6)? 1 : 4; 

这样做,与如果很凌乱:

int i_temp; 
if (A == 6) 
    i_temp = 1; 
else 
    i_temp = 4; 
const int i = i_temp; 

你不能把初始化内部的if/else,因为它的变化范围。但引用和常量变量只能在初始化时绑定。

10

我通常选择的时候我有很多重复的代码,否则三元操作符。

if (a > 0) 
    answer = compute(a, b, c, d, e); 
else 
    answer = compute(-a, b, c, d, e); 

对于三元运算符,可以用以下方法完成。

answer = compute(a > 0 ? a : -a, b, c, d, e); 
+12

个人我会做'aVal = a> 0? a:-a; answer = compute(aVal,b,c,d,e);'特别是如果'b','c','d'和'e'也需要处理。 – corsiKa 2010-07-22 21:56:47

+10

为什么在这个例子中使用条件?只需获取Abs(a)并调用compute()一次。 – Ash 2010-07-23 05:32:17

+2

是的,我没有创造出最好的例子。 :) – 2010-07-27 18:33:10

1

三元运算符可以包括一个rvalue内,而如果 - 则 - 否则不能;在另一方面,如果 - 则 - 否则可以执行循环和其它语句,而三元运算只能执行(可能无效)右值。

在一个相关的说明,& &和||运算符允许一些难以用if-then-else实现的执行模式。例如,如果一个人有几个函数调用,并希望执行一段代码,如果其中任何失败,它可以很好地使用& &操作完成。如果没有该操作员,则需要冗余代码,转到或附加标志变量。

46

这是相当多的其他的答案覆盖,但“这是一个表达”并没有真正解释为什么会这样有用...

在像C++和C#语言中,可以定义局部常量(在方法体内)使用它们。这是不可能用传统的if/then语句,因为一个const所有的值必须被该单个语句中指定:

const int speed = (shiftKeyDown) ? 10 : 1; 

不一样:

const int speed; 
if (shifKeyDown) 
    speed = 10; // error - can't assign to a const 
else 
    speed = 1;  // error 

在类似的你可以在其他代码中嵌入第三个表达式。以及使源代码更紧凑(和在某些情况下更可读的结果),也可以使所生成的机器代码更加紧凑和有效的:

MoveCar((shiftKeyDown) ? 10 : 1); 

...可以比具有以产生较少的代码调用相同的方法两次:

if (shiftKeyDown) 
    MoveCar(10); 
else 
    MoveCar(1); 

当然,这也是一个更方便,更简洁的形式(打字,少重复,如果你有,如果复制的代码块中的可减少错误的机会/其他)。在这样干净的“普通模式”的情况:

object thing = (reference == null) ? null : reference.Thing; 

...这简直是更快的读取/解析/理解(一旦你习惯了它),比长篇大论的if/else相等的,所以它可以帮助你更快速地“修整”代码。

当然,仅仅因为它是有用并不意味着它是在任何情况下使用最好的事情。我建议只使用它来代替含义较为明确(或更明确)的短代码,如果使用更复杂的代码,或者将三元运算符嵌套在一起,可能会使代码变得极其困难读。

+0

@JaminGrey _“这并不意味着,当常量被创建时,它被设置为10或1。”_你的意思是_does_是什么意思?不正确的注释可能会导致对新C++程序员的混淆,而不是您试图清除的问题;) – Clonkex 2013-11-07 03:02:59

+0

@Clonkex对,谢谢。 =)让我再试一次: – 2013-11-07 04:38:32

+5

对于未来的读者来说,通过“* const int speed =(shiftKeyDown)?10:1; *”,这意味着当第一次创建常量*时,它被设置为10或1.它**并不意味着每次访问常量时都会执行检查。 (只是说一个更新的C++程序员感到困惑) – 2013-11-07 04:39:16

10

一个很酷的用法是:

x = foo ? 1 : 
    bar ? 2 : 
    baz ? 3 : 
      4; 
+10

在PHP中注意这一点,三元运算符在PHP中关联错误的方式。从本质上讲,如果'foo'是错误的,那么整个事情将评估为4,而不进行其他测试。 – 2015-03-21 20:16:36

+4

@TomBusby - 哇。还有一个讨厌PHP的原因,如果你是一个已经讨厌PHP的人。 – 2017-08-07 04:39:03

4

虽然上面的答案是有效的,和我一起可读性是重要的同意,有2分还需要考虑的要点:

  1. 在C#6 ,你可以有表达式的方法。

这使得它特别简明使用三元:

string GetDrink(DayOfWeek day) 
    => day == DayOfWeek.Friday 
     ? "Beer" : "Tea"; 
当涉及到隐式类型转换
  • 行为不同。
  • 如果你有类型T1T2这都可以隐式转换为T,那么下面呢工作:

    T GetT() => true ? new T1() : new T2(); 
    

    (因为编译器试图确定三元的类型表达式,并且在T1T2之间没有转换。)

    另一方面,if/else版本低于d OES工作:

    T GetT() 
    { 
        if (true) return new T1(); 
        return new T2(); 
    } 
    

    因为T1转化为T,所以是T2

    3

    有时候,它可以使一个布尔值的分配更容易第一眼就阅读:

    // With 
    button.IsEnabled = someControl.HasError ? false : true; 
    
    // Without 
    button.IsEnabled = !someControl.HasError;