2010-07-22 20 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;