2013-04-01 32 views
8

我想轉換if語句來切換情況下(可讀性)如果條件中開關的情況下

1)我讀過的開關語句是一般aweful - 是真的嗎? https://stackoverflow.com/questions/6097513/switch-statement-inside-a-switch-statement-c

2)該語句是這樣的:

switch (Show) 
       { 
        case Display.Expense: 
         if (expected.EXPENSE != true) 
          break; 
        case Display.NonExpense: 
         if (expected.EXPENSE == true) 
          break; 
        case Display.All: 
         //Code 
         break; 
       } 

錯誤是:

控制不能從一個case標籤( '殼體1:' 通過落)到另一個

這是原來的if語句:

if ((Show == Display.All) || (expected.EXPENSE == true && Show == Display.Expense) || (expected.EXPENSE == false && Show == Display.NonExpense)) 
{ 
    //Code 
} 
+0

考慮有關錯誤的這個問題。 http://stackoverflow.com/questions/6696692/control-cannot-fall-through-from-one-case-label –

+1

'開關'是針對**不同的**行爲在不同情況下。在diffrenet的情況下,你只有**行爲**,因此@Dennis寫道你不需要'switch'。 –

+0

它不清楚你正在試圖通過使用if語句,除了'break'開關的情況下什麼都不做。如果你想在case情況下使用一個if語句,你需要一個其他條件,這也是一個'break' –

回答

7

編譯器不會明白你的意思在這裏。

switch (Show) 
{ 
    case Display.Expense: 
     if (expected.EXPENSE != true) 
      break; 
     // missing break here 
    case Display.NonExpense: 

編譯器將無法連接點,瞭解您if語句內break;聲明鏈接到switch聲明。相反,它會嘗試將它鏈接到一個循環,因爲break;自己的語句只能用於循環,才能打破它。

這意味着您的case塊缺少它的break語句來完成它,因此編譯器會抱怨。

而不是試圖從switch聲明中擰出必要的代碼,而是將分解您原來的if聲明。

這是你的:

if ((Show == Display.All) || (expected.EXPENSE == true && Show == Display.Expense) || (expected.EXPENSE == false && Show == Display.NonExpense)) 
{ 
    //Code 
} 

這是我會怎麼寫呢:

bool doDisplayExpected = 
     (Show == Display.All) 
    || (Show == Display.Expense && expected.EXPENSE) 
    || (Show == Display.NonExpense && !expected.EXPENSE); 
if (doDisplayExpected) 
{ 
    // code 
} 

你不在一行收拾一切。

而且,我想嘗試的名字屬性,使他們更容易閱讀,我將在EXPENSE屬性重命名爲IsExpense,這樣上面的代碼會這樣寫:

bool doDisplayExpected = 
     (Show == Display.All) 
    || (Show == Display.Expense && expected.IsExpense) 
    || (Show == Display.NonExpense && !expected.IsExpense); 
if (doDisplayExpected) 
{ 
    // code 
} 

然後,理想情況下,我將重構出來的子表達式的方法:

bool doDisplayExpected = 
     ShowAll() 
    || ShowExpense(expected) 
    || ShowNonExpense(expected); 
if (doDisplayExpected) 
{ 
    // code 
} 

public bool ShowAll() 
{ 
    return Show == Display.All; 
} 

public bool ShowExpense(Expected expected) 
{ 
    return Show == Display.Expense && expected.EXPENSE; 
} 

public bool ShowNonExpense(Expected expected) 
{ 
    return Show == Display.NonExpense && !expected.EXPENSE; 
} 

然後你就可以把表達式回到if語句:

if (ShowAll() || ShowExpense(expected) || ShowNonExpense(expected)) 
{ 
    // code 
} 

這應該更容易閱讀,並在以後更改。

+0

+1那樣讀取代碼。只有改變我建議的是讓所有東西都成爲一個屬性(假設'預期'是同一類的成員) – SolutionYogi

2

提供的else部分爲他們每個人的,所以它不會拋出錯誤,但是因爲別人說,你其實並不在這種情況下,需要switch

switch (Show) 
{ 
    case Display.Expense: 
     if (expected.EXPENSE != true) 
      // do what you want 
      break; 
     else 
      // do what you want 
      break; 
    case Display.NonExpense: 
     if (expected.EXPENSE == true) 
      // do what you want 
      break; 
     else 
      // do what you want 
      break; 
    case Display.All: 
     //Code 
     break; 
} 
+0

@DavinTryon我同意,但我想顯示是什麼導致了錯誤。任何我編輯它的方式。 –

3

如果你想可讀性,剛剛扔掉你的語法垃圾:

if (Show == Display.All || expected.EXPENSE && Show == Display.Expense || !expected.EXPENSE && Show == Display.NonExpense) 
{ 
    //Code 
} 
+2

同意。交換機沒有增加任何東西 –

5

使用if語句,並提取複雜的條件下進入方法,例如

if (ShowAll() || ShowExpense()) 
{ 
} 

記得OOP和多態性每次你寫這樣的'開關',增加另一個 的情況下,該代碼將是一個噩夢

看到thissimilar (C++)說明有關轉換開關

PS,如果你有興趣使您的代碼乾淨和可讀性,可以閱讀Smalltalk Best Practice Patterns by Kent Beck和/或Clean Code by Uncle Bob 我真的很喜歡他們兩個, 強烈推薦。

+0

是不是添加更多的方法來使代碼更大 - >更復雜? – AngelicCore

+1

它會使代碼更大,是的。更復雜?我不信。但未來肯定會更容易支持和維護。讓你的方法很小,將它們逐個排列,這樣它們以自然的方式排列(從當前調用的方法就在下面),你將能夠像報紙 –

0

重構出if語句,所以你可以表達它像這樣:

if (isDisplayAll() || isExpense(expected) || isNonExpense(expected)) 
{ 
    // Code 
} 

提取的邏輯:

private bool isDisplayAll() 
{ 
    return (Show == Display.All); 
} 

private bool IsExpense(Expected expected) 
{ 
    return expected.EXPENSE && (Show == Display.Expense); 
} 


private bool IsNonExpense(Expected expected) 
{ 
    return !expected.EXPENSE && (Show == Display.NonExpense); 
} 
1

您出現此錯誤的原因是您沒有定義break語句。

您有條件地定義了break

  switch (Show) 
      { 
       case Display.Expense: 
        if (expected.EXPENSE != true) 
         break; 

       // Note that the break above is in scope of you if statement, and will 
       // result in a compiler error 
       case Display.NonExpense: 
        ... 
      } 

要麼確保每個case語句都有自己的break或組分別如下case語句。

  switch (Show) 
      { 
       case Display.Expense: 
       case Display.All: 
        // do stuff 
        // Expense and All have the same behavior 
      } 
0

同意丹尼斯,你不想爲這個問題切換案例。

雖然可能不太可讀,你也可以使用更短:

if (Show == Display.All || (expected.EXPENSE == (Show == Display.Expense))) 
{ 
    //Code 
} 
12

首先,我注意到,你忘了問你的第二點的問題。所以我會問你一些問題以解決你的第二點:

「can not fall through」錯誤是什麼意思?

與C和C++不同,C#不允許從一個開關部分意外跌落到另一個開關部分。每個開關部分必須有一個「無法到達的終點」;它應該以休息,轉到,返回,拋出或(很少)無限循環結束。

這可以防止忘記放入休息室和意外「掉落」的常見錯誤。

你已經編寫了你的​​代碼,就像fall-through是合法的;我的猜測是你是C程序員。

如何強制落下,通過在C#中?

像這樣:

switch (Show) 
{ 
case Display.Expense: 
    if (expected.EXPENSE != true) 
     break; 
    else 
     goto case Display.All; 
case Display.NonExpense: 
    if (expected.EXPENSE == true) 
     break; 
    else 
     goto case Display.All; 
case Display.All: 
    //Code 
    break; 
} 

現在的可達性分析可以判斷,無論哪個分支的「如果」被採用,開關部分端點不可達。

這是很好的風格?

號原密碼是很多的可讀性。

我讀過switch語句,總的來說是非常好的 - 這是真的嗎?

意見而變化。當行爲不以複雜方式進行交互的少數非常「清晰」的選擇時,Switch語句非常有用。有些人會告訴你,交換邏輯應該由虛擬方法或訪問者模式來處理,但也可能會被濫用。

我應該在這個特殊的情況下,使用一個開關?

我不會。

如何改善我的代碼?

if ((Show == Display.All) || 
    (expected.EXPENSE == true && Show == Display.Expense) || 
    (expected.EXPENSE == false && Show == Display.NonExpense)) 
{ 
    //Code 
} 

首先,不命名的東西在C#中全部大寫。

其次,不要比較布爾人的真假。他們已經是布爾人了!如果你想知道陳述X的真相,你不會用英語說「是真的,X是真的嗎?」你會說「X是真的嗎?」

我可能會寫:

if (Show == Display.All || 
    Show == Display.Expense && expected.Expense || 
    Show == Display.NonExpense && !expected.Expense) 
{ 
    //Code 
} 

,或者甚至更好,我會抽象測試遠到它自己的方法:

if (canDisplayExpenses()) 
{ 
    //Code 
} 

或抽象整個事情遠:

DisplayExpenses(); 
+0

非常好的解釋,ty :) – AngelicCore