使用条件?:(三元)运算符的好处

KCh*_*oux 101 c# conditional-operator

与标准的if-else语句相比,?:运算符有什么好处和缺点.显而易见的是:

有条件的?:运营商

  • 在处理直接价值比较和分配时更简洁,更简洁
  • 似乎不像if/else构造那样灵活

标准If/Else

  • 可以应用于更多情况(例如函数调用)
  • 通常是不必要的长

根据声明,可读性似乎各不相同.在第一次接触到?:运算符后的一段时间内,我花了一些时间来精确地消化它是如何工作的.您是否会建议尽可能使用它,或者坚持if/else,因为我与许多非程序员一起工作?

Dan*_*Tao 122

我基本上建议只在结果语句非常短时才使用它,并且在不牺牲可读性的情况下代表if/else等效项的简洁性显着提高.

好例子:

int result = Check() ? 1 : 0;
Run Code Online (Sandbox Code Playgroud)

不好的例子:

int result = FirstCheck() ? 1 : SecondCheck() ? 1 : ThirdCheck() ? 1 : 0;
Run Code Online (Sandbox Code Playgroud)

  • 我总是从一个简单的开始,随着时间的推移使它变得更加复杂,直到它完全不可读. (39认同)
  • 第二个示例中的可读性可以通过更好的格式化轻松纠正.但是,正如OP所推荐的那样,它归结为可读性和简洁性与冗长性. (9认同)
  • @mquander,你确定吗?http://www.merriam-webster.com/dictionary/concise (6认同)
  • 好的电话,但为了记录,这是"简洁". (5认同)
  • 不是OP问题的一部分,但重要的是要注意事实是你不能将'return`作为三元运算结果的一部分.例如:`check()?返回1:返回0;`不起作用,但是`return check()?1:0;`会.在编程中找到这些小怪癖总是很有趣. (4认同)

Jas*_*ams 50

其他答案几乎涵盖了这一点,但"它是一个表达式"并没有真正解释为什么它如此有用......

在C++和C#等语言中,您可以使用它们定义本地只读字段(在方法体内).对于传统的if/then语句,这是不可能的,因为必须在该单个语句中分配只读字段的值:

readonly int speed = (shiftKeyDown) ? 10 : 1;
Run Code Online (Sandbox Code Playgroud)

是不一样的:

readonly int speed;  
if (shifKeyDown)  
    speed = 10;    // error - can't assign to a readonly
else  
    speed = 1;     // error  
Run Code Online (Sandbox Code Playgroud)

以类似的方式,您可以在其他代码中嵌入第三个表达式.除了使源代码更紧凑(在某些情况下更具可读性)之外,它还可以使生成的机器代码更紧凑和高效:

MoveCar((shiftKeyDown) ? 10 : 1);
Run Code Online (Sandbox Code Playgroud)

...可能生成的代码少于必须调用两次相同的方法:

if (shiftKeyDown)
    MoveCar(10);
else
    MoveCar(1);
Run Code Online (Sandbox Code Playgroud)

当然,它也是一种更方便和简洁的形式(更少的输入,更少的重复,并且如果你必须在if/else中复制代码块,可以减少错误的机会).在干净的"常见模式"案件中,如下所示:

object thing = (reference == null) ? null : reference.Thing;
Run Code Online (Sandbox Code Playgroud)

...读取/解析/理解(一旦习惯了)比快速if/else等效更快,因此它可以帮助您更快地"扫描"代码.

当然,仅仅因为它有用并不意味着它在每种情况下都是最好的用法.我建议只使用它代码的短代码,其中含义明确(或更清楚)使用?:- 如果你在更复杂的代码中使用它,或者将三元运算符嵌套在彼此之内,它会使代码难以读取.

  • 对于未来的读者来说,通过"*const int speed =(shiftKeyDown)?10:1;*",这意味着当第一次创建常量*时,它被设置为10或1.它**不't**表示每次访问常量时都会进行检查.(只是让更新的C++程序员感到困惑) (5认同)
  • ...或换句话说,`const`是常量,即在声明它的语句执行后它不能被改变. (2认同)

Rya*_*ght 14

我通常选择三元运算符,否则我会有很多重复的代码.

if (a > 0)
    answer = compute(a, b, c, d, e);
else
    answer = compute(-a, b, c, d, e);
Run Code Online (Sandbox Code Playgroud)

使用三元运算符,可以通过以下方式实现.

answer = compute(a > 0 ? a : -a, b, c, d, e); 
Run Code Online (Sandbox Code Playgroud)

  • 我个人会做'aVal = a> 0?a:-a; answer = compute(aVal,b,c,d,e);`特别是如果`b`,`c`,`d`和`e`也需要处理. (12认同)
  • 为什么在这个例子中使用条件?只需获取Abs(a)并调用compute()一次. (10认同)
  • 是的,我没有创造出最好的例子.:) (2认同)

小智 12

我发现在进行Web开发时,如果我想将变量设置为请求中发送的值(如果已定义)或者某个默认值(如果不是),则会特别有用.

  • web dev中的+1默认值是一个很好的例子,是使用三元运算符的好地方 (3认同)

aib*_*aib 12

一个非常酷的用法是:

x = foo ? 1 :
    bar ? 2 :
    baz ? 3 :
          4;
Run Code Online (Sandbox Code Playgroud)

  • 在PHP中要小心,三元运算符在PHP中关联错误的方式.基本上,如果`foo`为false,那么整个事情将评估为4而不进行其他测试. (10认同)
  • @TomBusby - 哇.如果你是一个已经厌恶PHP的人,那么讨厌PHP的又一个原因. (4认同)

HOC*_*OCA 6

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

if(<boolCondition>) {
    <variable> = <value>;
}
else {
    <variable> = <anotherValue>;
}
Run Code Online (Sandbox Code Playgroud)

可以很容易地转换为:

<variable> = <boolCondition> ? <value> : <anotherValue>;
Run Code Online (Sandbox Code Playgroud)

在需要 if/else if/else、嵌套 if/else 或 if/else 分支逻辑(导致评估多行)的情况下,我会避免使用三元运算符。在这些情况下应用三元运算符可能会导致代码不可读、混乱且难以管理。希望这可以帮助。


ian*_*sme 6

条件运算符非常适合短期条件,如下所示:

varA = boolB ? valC : valD;
Run Code Online (Sandbox Code Playgroud)

我偶尔会使用它,因为用这种方式写东西需要的时间更少......不幸的是,有时候浏览代码的其他开发人员会错过这种分支.另外,代码通常不会那么短,所以我通常会通过放置代码来帮助提高可读性.和:在不同的行上,像这样:

doSomeStuffToSomething(shouldSomethingBeDone()
    ? getTheThingThatNeedsStuffDone()
    : getTheOtherThingThatNeedsStuffDone());
Run Code Online (Sandbox Code Playgroud)

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

if (shouldSomethingBeDone()) {
    doSomeStuffToSomething(getTheThingThatNeedsStuffDone());
    doSomeAdditionalStuff();
} else {
doSomeStuffToSomething(getTheOtherThingThatNeedsStuffDone());
}
Run Code Online (Sandbox Code Playgroud)

或添加另一个条件:

if (shouldSomethingBeDone()) {
    doSomeStuffToSomething(getTheThingThatNeedsStuffDone());
    doSomeAdditionalStuff();
} else if (shouldThisOtherThingBeDone()){
    doSomeStuffToSomething(getTheOtherThingThatNeedsStuffDone());
}
Run Code Online (Sandbox Code Playgroud)

所以,最后,它是为了你现在的便利性(使用时间更短:?)以及后来对你(以及其他人)的便利.这是一个判断调用...但与所有其他代码格式问题一样,唯一真正的规则是保持一致,并且对那些必须维护(或评级!)代码的人视觉上有礼貌.

(所有代码眼睛编译)


Ken*_*uys 5

使用三元运算符时要认识到的一点是表达式而不是语句.

在像scheme这样的函数式语言中,区别不存在:

(如果(> ab)ab)

条件?:运算符"似乎不像if/else构造那样灵活"

在功能语言中它是.

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


小智 5

虽然上述答案是有效的,并且我同意可读性很重要,但还有两点需要考虑:

  1. 在C#6中,您可以使用表达式方法.

这使得使用三元组特别简洁:

string GetDrink(DayOfWeek day) 
   => day == DayOfWeek.Friday
      ? "Beer" : "Tea";
Run Code Online (Sandbox Code Playgroud)
  1. 当涉及隐式类型转换时,行为会有所不同.

如果您有类型T1T2那都可以隐式转换为T,那么以下就不能正常工作:

T GetT() => true ? new T1() : new T2();
Run Code Online (Sandbox Code Playgroud)

(因为编译器试图确定三元表达式的类型,和之间不存在转换T1T2).

另一方面,if/else下面的版本确实有效:

T GetT()
{
   if (true) return new T1();
   return new T2();
}
Run Code Online (Sandbox Code Playgroud)

因为T1被转换成了T等等T2


Tyl*_*uso 5

有时它可以使乍一看的bool值的分配更容易阅读:

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

// Without
button.IsEnabled = !someControl.HasError;
Run Code Online (Sandbox Code Playgroud)