65

switchステートメントを含むループから抜け出す方法を理解するのに問題があります。ブレークは、ループではなく、スイッチからブレークアウトします。

これにはおそらくもっとエレガントな解決策があります。trueで始まり、falseに設定され、ループを終了するフラグを実装しました。より良い解決策を提供できますか?

背景:このコードは、バーコードワークフローシステムで使用されます。バーコードスキャナーが組み込まれたPocketPCがあります。このコードは、これらの機能の1つで使用されます。ルーチン全体でさまざまなデータの入力をユーザーに求めます。このピースを使用すると、PocketPC端末にその情報を表示するいくつかのインベントリレコード(ページングされた結果)をスクロールでき、完了の場合は「D」、終了するには「Q」を入力できます。

改善が必要な現在のC#の例を次に示します。

do
{
    switch (MLTWatcherTCPIP.Get().ToUpper())
    {
        case "": //scroll/display next inventory location
            MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown();
            break;
        case "P": //scroll/display previous inventory location
            MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown();
            break;
        case "D": //DONE (exit out of this Do Loop)
            // break; // this breaks out of the switch, not the loop
            // return; // this exists entire method; not what I'm after
            keepOnLooping = false;
            break;
        case "Q": //QUIT (exit out to main menu)
            return;
        default:
            break;
    }
} while (keepOnLooping);

これは、VB.NETでこれを行うコードの例です。

Do
    Select Case MLTWatcherTCPIP.Get().ToUpper
        Case "" ''#scroll/display next inventory location
            MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown()
        Case "P" ''#scroll/display previous inventory location
            MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextUp()
        Case "D" ''#DONE (exit out of this Do Loop)
            Exit Do
        Case "Q" ''#QUIT (exit out to main menu)
            Return
    End Select
Loop

ありがとう、

4

15 に答える 15

53

私はそれを避けようとしますが、あなたは使うことができます...

後藤

ただし、熊手を持った怒っている暴徒は、そうすることを選択した場合、職業上の危険になります。

于 2009-12-31T22:56:09.407 に答える
50

このフォームは、これまでになく少し読みやすくなっています。

bool done = false;
while (!done) 
{ 
    switch (MLTWatcherTCPIP.Get().ToUpper()) 
    { 
        case "": //scroll/display next inventory location 
            MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown(); 
            break; 
        case "P": //scroll/display previous inventory location 
            MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown(); 
            break; 
        case "D": //DONE (exit out of this Do Loop) 
            done = true;
            break; 
        case "Q": //QUIT (exit out to main menu) 
            return; 
        default: 
            break; 
    } 
}
于 2009-12-31T23:22:58.103 に答える
31

ここでの1つのオプションは、このループをメソッド( "extract method")にリファクタリングし、を使用することreturnです。

于 2009-12-31T22:58:44.837 に答える
12

私が知っている他の唯一の方法は恐ろしい後藤です。 MSDNもこれを言っています。

ただし、この場合に使用する理由はわかりません。実装した方法は正常に機能し、gotoよりも保守しやすくなっています。私はあなたが持っているものを保持します。

于 2009-12-31T22:56:34.227 に答える
10

マルチレベルのブレークにはgotoステートメントを使用する必要があります。これは、C#で唯一の「クリーンな」方法のようです。フラグを使用することも有用ですが、ループを実行するための他の苦境がある場合は、追加のコードが必要です。

http://msdn.microsoft.com/en-us/library/aa664756(VS.71).aspx

他のいくつかの非C言語には、実行することによってマルチレベルのブレークがあることに注意するのは興味深いかもしれません(ただし、Javaは、続行を装ったgotoを使用するので、同じように役に立ちません。。:P)break levels;

于 2009-12-31T22:55:21.533 に答える
8

ループを継続するためにブール値を返すメソッドにスイッチをラップしてみませんか?コードを読みやすくするという副次的な利点があります。結局、gotoステートメントは必要ないと誰かが論文を書いたのには理由があります;)

do
{
    bool keepOnLooping = TryToKeepLooping();
} while (keepOnLooping);

private bool TryToKeepLooping()
{
    switch (MLTWatcherTCPIP.Get().ToUpper())
    {
        case "": //scroll/display next inventory location
            MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown();
            break;
        case "P": //scroll/display previous inventory location
            MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown();
            break;
        case "D": //DONE (exit out of this Do Loop)
            // break; // this breaks out of the switch, not the loop
            // return; // this exists entire method; not what I'm after
            return false;
        case "Q": //QUIT (exit out to main menu)
            return true;
        default:
            break;
    }

    return true;
}
于 2009-12-31T23:12:22.017 に答える
7

外側のループから簡単に抜け出すことはできませんが、できcontinueます。

ロジックを逆にすると、これが得られます。breakswitchステートメントの直後にループを終了する必要があることに注意してください。

私の意見では、これはあまり読みやすいコードではなく、フラグが最適だと思います。

   do
         {
            switch (Console.ReadKey().KeyChar.ToString())
            {
                case "U":
                    Console.WriteLine("Scrolling up");
                    continue;

                case "J":
                    Console.WriteLine("Scrolling down");
                    continue;

                case "D": //DONE (exit out of this Do Loop)
                    break;

                case "Q": //QUIT (exit out to main menu)
                    return;

                default:
                    Console.WriteLine("Continuing");
                    continue;
            }

            break;

        } while (true);

        Console.WriteLine("Exited");
于 2012-08-01T21:53:05.627 に答える
4

フラグはこれを行うための標準的な方法です。私が知っている他の唯一の方法は、を使用することgotoです。

于 2009-12-31T22:55:23.810 に答える
2

switchステートメントをステートメントに置き換えることができますif/else。不要gotoで、breakステートメントはループを終了します。

do
{
  String c = MLTWatcherTCPIP.Get().ToUpper();

  if (c = "")
    MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown();
  else if (c = "P")
    MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextUp();
  else if (c = "D")
     break;
  else if (c = "Q")
    return;
  else
  {
    // Handle bad input here.
  }
} while (keepLooping)
于 2009-12-31T23:13:23.730 に答える
1

whileIMO、これはループから抜け出すための完璧な方法のようです。それは副作用なしであなたが期待することをします。私はすることを考えることができました

if(!keepOnLooping)
  break;

しかし、それは実行に関しては実際には何の違いもありません。

于 2009-12-31T22:57:19.610 に答える
1

それを関数にラップし、returnステートメントを使用して終了します。どのようにそのことについて?

于 2009-12-31T23:07:25.793 に答える
1

次のように記述します。

case "Exit/Break" :
                  //Task to do
                    if(true)
                      break;

この休憩は、どのような場合にも関連付けられません。whileループに属します。

于 2013-10-10T06:08:18.160 に答える
0

switchステートメントをfor/foreachループに変更できます。条件が満たされたら、「keepOnLooping」をfalseに設定し、breakを使用してループから抜け出します。残りはそれ自身の世話をする必要があります。

于 2009-12-31T23:09:09.333 に答える
0

もう1つの(それほど優れていない)代替手段は、case「ループから抜け出す」必要がある場所をifすぐに処理して、switchブロックから移動することです。スイッチケースが非常に長い場合、それほどエレガントではありません。

do
{
    var expression = MLTWatcherTCPIP.Get().ToUpper();
    if (expression = "D") //DONE (exit out of this Do Loop)
    {   
        statement;
        break;
    }

    switch (expression)
    {
        case "": //scroll/display next inventory location
            MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown();
            break;
        case "P": //scroll/display previous inventory location
            MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown();
            break;
        case "Q": //QUIT (exit out to main menu)
            return;
        default:
            break;
    }
} while (true); //or whatever your condition is

また、ループから抜け出すだけで、式自体の計算は簡単である(変数の読み取りなど)ことを考慮して、caseそれ自体をループの条件の一部にすることもできます。while

do
{
    switch (expression)
    {
        case "": //scroll/display next inventory location
            MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown();
            break;
        case "P": //scroll/display previous inventory location
            MLTWatcherTCPIP.TerminalPrompt.ScrollBodyTextDown();
            break;
        case "Q": //QUIT (exit out to main menu)
            return;
        default:
            break;
    }
} while (condition && expression != "D");

また、すべてを新しいメソッド(これに対する最も洗練されたソリューション)にリファクタリングすることが何らかの理由で受け入れられない場合は、匿名のデリゲートを使用して既存のメソッド内で同じことを行うこともできます。

于 2013-10-15T08:14:54.457 に答える
-2

うまくいくかもしれないし、うまくいかないかもしれないが、ラムダは楽しみのためだけにそれを試してみませんか

while(  (expr) => (){
switch(expr){
case 1: dosomething; return true; 
case 2 : something;return true;
case exitloop:return false;}
});   
于 2017-08-23T21:53:34.767 に答える