2017-03-14 26 views
-1

在我的程序中,我有一個方法,它有運行時總是使用的代碼。但是,在相同的方法中,我有if語句,它們基於狀態機分支代碼。我們只是(爲了簡單)說它是由兩個值組成的。是否有可能逃離`if ... elseif ... else`語句,比如`break`對循環有用,對於方法用`return`呢?

using System; 
using System.Console; 

int stateA = 1; 
int stateB = 1; 

void Main() { 
    while (true) { 
     Method(); 
    } 
} 

void Method() { 
    Console.WriteLine("This will always be printed no matter what happens."); 

    if (stateA == 1 && stateB == 1) 
    { 
     Console.WriteLine("State 1"); 
     stateB = 2; 
     // goto endofifstatement; 
    } 
    elseif (stateA == 1 && stateB == 2) 
    { 
     Console.WriteLine("State 2"); 
     stateA = 2; 
     // goto endofifstatement; 
    } 
    else { 
     Console.WriteLine("Resetting States...") 
     stateA = 1; 
     stateB = 2; 
     // goto endofifstatement; 
    } 
    // endofifstatement: 

    Console.WriteLine("This will always also be printed no matter what happens."); 
    Console.WriteLine(""); 
} 

現在。此代碼現在的問題是,if...elseif...else塊的所有三個部分都將在每次循環迭代中運行。
當然,有幾種方式,我可以解決這個問題:

  • 獨立(封裝)的if...elseif....else語句轉換成其自己的方法,並使用return爆發。
  • 更換ifelseif塊的內容和表達式,但這隻適用於這種情況。如果我們有幾百個案例會發生什麼?
  • 使用goto,但沒有人真的再使用它了。 (注意上面的代碼片段)
  • 使用多個switch...case或IF語句,嵌套在對方內部。

問:

是否有可能逃出的if...elseif...else聲明像break確實給一個循環,並return確實爲方法呢?

因此,對於上面的例子中,輸出應該是:

This will always be printed no matter what happens. 
State 1 
This will always also be printed no matter what happens. 

This will always be printed no matter what happens. 
State 2 
This will always also be printed no matter what happens 

This will always be printed no matter what happens. 
Resetting States... 
This will always also be printed no matter what happens 

,重複,而不是:

This will always be printed no matter what happens. 
State 1 
State 2 
Resetting States... 
This will always also be printed no matter what happens 

This will always be printed no matter what happens. 
State 1 
State 2 
Resetting States... 
This will always also be printed no matter what happens 

AAAND重複。另外,如果我們將這個擴展爲兩個以上的變量和可能的值,它應該能夠保持,即使在CPU速度的範圍內,因爲我們只是基本上脫離了一個塊。

+1

也許只是在'for'循環和'if'' else'之上的計數器? –

+2

你是什麼意思所有3個分支與當前代碼一起運行?我認爲你需要重新考慮這一點。 – itsme86

+0

@ itsme86是的。我只是意識到。 – aytimothy

回答

0

是的,goto語句會導致問題,因爲您必須尋找下一個要執行的行。另外,它可能會在特別複雜的代碼中導致意外的行爲。

您有許多選項可供您使用。我的首選是重寫你的邏輯,以便讀取更容易(選項1),但我會展示我看到的。

選項1:重寫

void Method() { 
    Console.WriteLine("This will always be printed no matter what happens."); 
    if (stateA == 1) { 
     if (stateB == 1) { 
      Console.WriteLine("State 1"); 
      stateB = 2; 
     } 
     else { 
      Console.WriteLine("State 2"); 
      stateA = 2; 
     } 
    } 
    else { 
     Console.WriteLine("Resetting States...") 
     stateA = 1; 
     stateB = 2; 
    } 

    Console.WriteLine("This will always also be printed no matter what happens."); 
    Console.WriteLine(""); 
} 

選項2:單獨的方法

void UpdateState() { 
    if (stateA == 1 && stateB == 1) { 
     Console.WriteLine("State 1"); 
     stateB = 2; 
     return; 
    } 
    elseif (stateA == 1 && stateB == 2) { 
     Console.WriteLine("State 2"); 
     stateA = 2; 
     return; 
    } 
    else { 
     Console.WriteLine("Resetting States...") 
     stateA = 1; 
     stateB = 2; 
     return; 
    } 
} 
void Method() { 
    Console.WriteLine("This will always be printed no matter what happens."); 
    UpdateState(); 

    Console.WriteLine("This will always also be printed no matter what happens."); 
    Console.WriteLine(""); 
} 

選項3:嘗試/最後

void Method() { 
    Console.WriteLine("This will always be printed no matter what happens."); 
    try { 
     if (stateA == 1 && stateB == 1) { 
      Console.WriteLine("State 1"); 
      stateB = 2; 
      return; 
     } 
     elseif (stateA == 1 && stateB == 2) { 
      Console.WriteLine("State 2"); 
      stateA = 2; 
      return; 
     } 
     else { 
      Console.WriteLine("Resetting States...") 
      stateA = 1; 
      stateB = 2; 
      return; 
     } 
    } 
    finally { 
     Console.WriteLine("This will always also be printed no matter what happens."); 
     Console.WriteLine(""); 
    } 
} 

選項4:封裝/多態性 有許多設計模式適用於此。特別是,戰略想到。

+1

'選項2中的UpdateState()':單獨的方法不需要'return;' – GSP

+0

@GSP:並且,就此而言,原始代碼不需要'打破;'。上述答案的問題在於,它解決了比原始代碼更復雜的問題,但它確實是同樣的東西。 –

-1

根據我的理解,當elseif梯子長得很長時,您正在嘗試編寫更乾淨的代碼。如果情況和NOT CPU性能,那麼你有幾種選擇:

State模式

interface ASuitableNameState與方法getNextState其返回的ASuitableNameState類型。現在你可以有具體的實現,如class StateAOneBOne : ASuitableNameStateclass StateAZeroBOne : ASuitableNameState

StateAOneBOne中,您覆蓋了方法getNextState。你有return new StateAOneBTwo();

這樣你的if-else梯子消失了。您main可以改寫爲:

using System; 
using System.Console; 

ASuitableNameState currentState = new StateAOneBOne(); 

void Main() { 
    while (true) { 
     Method(); 
    } 
} 

void Method() { 
    consolw.writeLine("A and B are"); 
    console.writeLine(currentState.getA + currentState.getB); 
    currentState = currentState.getNextState(); 
} 

的缺點是,你有因爲有stateAstateB組合,創造儘可能多的參加。如果所有的組合都在(說)二十,那麼這種方法是可行的,否則不可行。