2012-11-11 19 views
11

考慮這個功能,你能想到的一個真值表:如何避免在C#中不可能的布爾狀態?

public Foo doSomething(bool a, bool b) { 

     if (a && b) return doAB(); 
    else if (a && !b) return doA(); 
    else if (!a && b) return doB(); 
    else if (!a && !b) return doNotANotB(); 

    else throw new Exception("Well done, you defeated boolean logic!"); 
} 

編譯器堅持去年else條款。但從真理表的角度來看,這是一個不可能的狀態。

是的,它的作品,是的,我可以忍受它。但我想知道是否有一些機制在C#中以避免這種類型的代碼,或者如果我錯過了明顯的東西?

UPDATE:
獎勵積分,和純粹出於好奇,是否有與這種不同的事情處理任何語言?也許這不是一個語言問題,而是一個聰明的編譯器(但邊緣案例將是難以想象的複雜,我想)。

+6

是的,我有這樣的機制:簡單地放棄最後一個「if」的條件。 – dasblinkenlight

+0

非常真實!潘打算。但如果可能的話,我希望代碼是「可讀的」或「富有表現力的」。請記住這是一個簡單的例子。而且在7個月內,我會抓住我的腦袋,想知道我在寫什麼時想的是什麼(因此是表達代碼的優先考慮)。 –

+0

如果這些動作與彼此不相關,我不會使用'if/else if'模式,而是使用四個單獨的'if'模塊,然後拋出異常以滿足編譯器。但在大多數情況下,「默認」操作完全符合空白的「else」。 –

回答

18

考慮到真值表,最後的條件完全是多餘的。它可以在不改變你的程序的邏輯被丟棄,就像這樣:

public MyType doSomething(bool a, bool b) { 

     if (a && b) return doAB(); 
else if (a && !b) return doA(); 
else if (!a && b) return doB(); 
else/*if (!a && !b)*/ return doNotANotB(); 
} 

現在你有一個最終的包羅萬象的if,和你的編譯器是幸福的。您不必完全刪除條件 - 我經常發現在備註中註明可讀性是個好主意。

+3

我其實喜歡留下注釋掉的代碼,因爲它記錄了最後一個分支的有效狀態。 +1 – usr

+0

是的,正如我在上面的評論中指出的那樣,這是真的。但是,有沒有一種方法可以在不訴諸隱含條件的情況下表達意圖?可能不會... –

+0

@BobbyB絕對不要急!從內部知道C#編譯器的人有機會看到這個問題,並與我們分享一個有洞察力的答案。 (我特指[Eric Lippert](http://stackoverflow.com/users/88656/eric-lippert),但不幸的是他最近沒有回答太多問題)。 – dasblinkenlight

2
public MyType doSomething(bool a, bool b) 
     { 
      switch(a) 
      { 
       case true: 
        if (b) return doAB(); 
        return doA(); 
       default: 
        if (b) return doB(); 
        return doNotANotB(); 

      } 

     } 

更新:

注意,你原來的說法居然是:

public MyType doSomething(bool a, bool b) 
     { 
      if (a && b) return doAB(); 
      if (a) return doA(); 
      if (b) return doB(); 
      return doNotANotB(); 
     } 

的樂趣和succintnes(如果沒有可讀性:P):

static MyType doSomething(bool a, bool b) 
     { 
      return a && b ? doAB() : a ? doA() : b ? doB() : doNotANotB(); 
     } 
+0

顯然不太可讀,但確實非常酷! –

+0

我認爲我更喜歡後者的例子。只要使用適當的變量和方法名稱,並且可能還有一些換行符和縮進,我不認爲它的可讀性較差。 –

+0

*點頭*,我很喜歡後者,儘管我覺得在嵌套的三元評估中很容易。 – Anthill

6

嘗試f#。如果它可以檢測與其匹配指令匹配的窮舉條件,那麼它不需要別的。

http://ganesansenthilvel.blogspot.co.at/2011/12/f-pattern-matching.html?m=1#

> let testAND x y = 
match x, y with 
| true, true -> true 
| true, false -> false 
| false, true -> false 
| false, false -> true 

> testAND true false;; 
val it: bool = true 

和一個不完整的規範

> let testAND x y = 
match x, y with 
| true, true -> true 
// Commented | true, false -> false 
| false, true -> false 
| false, false -> true 
> testAND true false;; 

編譯器會說

Microsoft.Fsharp.Core.MatchFailureExcption: The match cases were incomplete at:.... 
Stopped due to error 
7
if(a) return b ? doAB() : doA(); 
else return b ? doB() : doNotAnotB(); 

或更短:

return a ? (b ? doAB() : doA()) 
     : (b ? doB() : doNotAnotB());