الخروج من حلقة الوقت التي تحتوي على بيان التبديل

StackOverflow https://stackoverflow.com/questions/1987379

  •  22-09-2019
  •  | 
  •  

سؤال

أواجه مشكلة في معرفة كيفية الخروج من حلقة تحتوي على بيان التبديل. كسر كسر من المفتاح ، وليس الحلقة.

ربما يكون هناك حل أكثر أناقة لهذا. لقد قمت بتطبيق علامة تبدأ على أنها صحيحة وينتبط على خطأ وينهي الحلقة. هل يمكنك تقديم حل أفضل؟

الخلفية: يتم استخدام هذا الرمز في نظام سير عمل الرمز الشريطي. لدينا PocketPCs التي لديها ماسحات برمجية الشريطية مدمجة. يتم استخدام هذا الرمز في واحدة من هذه الوظائف. يطالب المستخدم للحصول على قطع مختلفة من البيانات خلال الروتين. تتيح لهم هذه القطعة التمرير عبر بعض سجلات المخزون التي تعرض تلك المعلومات على محطة 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

شكرًا،

هل كانت مفيدة؟

المحلول

أجد أن هذا النموذج يكون أكثر قابلية للقراءة أكثر من ذلك:

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; 
    } 
}

نصائح أخرى

سأحاول تجنب ذلك ، لكن يمكنك استخدام ...

اذهب إلى

ومع ذلك ، يصبح الغوغاء الغاضبون مع Pitchforks خطرًا مهنيًا إذا اخترت القيام بذلك.

أحد الخيارات هنا هو إعادة صياغة هذه الحلقة إلى طريقة ("طريقة الاستخراج") ، والاستخدام return.

الطريقة الوحيدة الأخرى التي أعرفها هي Goto اللعين. MSDN يقول هذا أيضا.

ومع ذلك ، لا أرى أي سبب لاستخدامه في هذه الحالة. الطريقة التي قمت بتنفيذها تعمل بشكل جيد ، وأكثر قابلية للصيانة من Goto. سأحتفظ بما لديك.

يجب عليك استخدام بيان GOTO لفترات متعددة المستوى. يبدو أنه الطريقة الوحيدة "النظيفة" في C#. يعد استخدام العلامة مفيدًا أيضًا ، ولكنه يتطلب رمزًا إضافيًا إذا كانت الحلقة تحتوي على مسببات أخرى للتشغيل.

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

قد يكون من المثير للاهتمام أن نلاحظ أن بعض اللغات الأخرى غير الأخرى لديها فترات راحة متعددة break مستويات; (Java غير مجدية بنفس القدر ، لأنه يستخدم Goto متنكرا في الوقت الذي تستمر ..: P)

لماذا لا تلتف المفتاح إلى طريقة تُرجع منطقية للحفاظ على الحلقات؟ سيكون لها فائدة جانبية لجعل الكود أكثر قابلية للقراءة. هناك سبب كتب أحدهم ورقة تقول إننا لا نحتاج إلى عبارات 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;
}

العلم هو الطريقة القياسية للقيام بذلك. الطريقة الأخرى الوحيدة التي أعرفها هي استخدام أ goto.

لا يمكنك الخروج بسهولة من الحلقة الخارجية ، ولكن يمكنك continue هو - هي.

إذا عكست منطقك ، فستحصل على هذا. لاحظ أن هناك أ break مباشرة بعد بيان التبديل للخروج من الحلقة.

هذا ليس رمزًا قابلاً للقراءة للغاية في رأيي ، وأعتقد أن العلم لا يزال أفضل.

   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");

يمكنك استبدال 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)

لفها في وظيفة واستخدم عبارة الإرجاع للخروج. ماذا عن ذلك؟

IMO ، يبدو أن هذه طريقة رائعة تمامًا للخروج من أ while عقدة. يفعل ما تتوقعه دون أي آثار جانبية. أستطيع أن أفكر في القيام به

if(!keepOnLooping)
  break;

ولكن هذا لا يختلف حقًا من حيث التنفيذ.

اكتب شيئًا مثل:

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

لن يرتبط هذا الاستراحة بأي حالة. سوف ينتمي إلى while عقدة.

يمكنك تغيير بيان التبديل إلى حلقة For/foreach. بمجرد استيفاء الحالة على مجموعة "KeepOnlooping" إلى False ثم استخدم Break للخروج من الحلقة. يجب أن يعتني الباقي بنفسه.

البديل الآخر (ليس كبيرًا) هو التعامل مع فريد من نوعه 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");

وأيضًا إذا كانت إعادة إنشاء كل شيء في طريقة جديدة (وهو الحل الأكثر أناقة لهذا) أمر غير مقبول لسبب ما ، فيمكنك أيضًا الاعتماد على مندوب مجهول لفعل الشيء نفسه داخل الطريقة الحالية.

قد تعمل أو لا تعمل ولكن لامدا لماذا لا تعطيها لقطة فقط للمتعة

while(  (expr) => (){
switch(expr){
case 1: dosomething; return true; 
case 2 : something;return true;
case exitloop:return false;}
});   
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top