2009-07-15 32 views
40

इस कोड नमूने में, पकड़ ब्लॉक से बाहरी पाश पर जारी रखने का कोई तरीका है?लूप

while 
{ 
    // outer loop 

    while 
    { 
     // inner loop 
     try 
     { 
      throw; 
     } 
     catch 
     { 
      // how do I continue on the outer loop from here? 
      continue; 
     } 
    } 
} 
+16

नेस्टेड लूप केवल निराशा का कारण बनते हैं। –

उत्तर

87

अद्यतन: यह प्रश्न my article on this subject. के लिए प्रेरणा थी महान प्रश्न के लिए धन्यवाद!


"जारी रखें" और "ब्रेक" "गोटो" के लिए सुखद वाक्यविन्यास से अधिक कुछ नहीं है। स्पष्ट रूप से उन्हें सुंदर नाम देकर और विशेष नियंत्रण संरचनाओं के लिए अपने उपयोग को सीमित करके, वे अब "सभी गेटो सभी समय खराब" भीड़ की चिल्ला नहीं खींचते हैं।

यदि आप क्या करना चाहते हैं एक जारी रखने के लिए करने के लिए बाहरी, आप बस एक लेबल बाहरी पाश के शीर्ष पर "गोटो" है कि लेबल को परिभाषित करने और फिर सकता है। अगर आपको लगा कि ऐसा करने से कोड की समझ में बाधा नहीं आती है, तो यह सबसे अधिक सुविधाजनक समाधान हो सकता है।

हालांकि, मैं इसे इस बात पर विचार करने का अवसर दूंगा कि आपका नियंत्रण प्रवाह कुछ रिफैक्टरिंग से लाभान्वित होगा या नहीं। जब भी मेरे पास नेस्टेड लूप में सशर्त "ब्रेक" और "जारी" होता है, तो मैं रिफैक्टरिंग पर विचार करता हूं।

पर विचार करें:

successfulCandidate = null; 
foreach(var candidate in candidates) 
{ 
    foreach(var criterion in criteria) 
    { 
    if (!candidate.Meets(criterion)) // Edited. 
    { // TODO: no point in continuing checking criteria. 
     // TODO: Somehow "continue" outer loop to check next candidate 
    } 
    } 
    successfulCandidate = candidate; 
    break; 
} 
if (successfulCandidate != null) // do something 

दो रिफैक्टरिंग तकनीक:

सबसे पहले, एक विधि के लिए भीतरी पाश निकालें:

foreach(var candidate in candidates) 
{ 
    if (MeetsCriteria(candidate, criteria)) 
    { 
     successfulCandidate = candidate; 
     break; 
    } 
} 

दूसरा, सभी छोरों समाप्त किया जा सकता? यदि आप लूपिंग कर रहे हैं क्योंकि आप कुछ खोज करने की कोशिश कर रहे हैं, तो इसे एक क्वेरी में दोबारा दोहराएं।

var results = from candidate in candidates 
       where criteria.All(criterion=>candidate.Meets(criterion)) 
       select candidate; 
var successfulCandidate = results.FirstOrDefault(); 
if (successfulCandidate != null) 
{ 
    do something with the candidate 
} 

यदि कोई लूप नहीं है तो तोड़ने या जारी रखने की कोई आवश्यकता नहीं है!

+5

+1 "... एक विधि में आंतरिक पाश निकालें।" जब मुझे नेस्टेड लूप दिखाई देता है तो मुझे कोड समीक्षाओं में बहुत औचित्य की आवश्यकता होती है। वे आमतौर पर पठनीयता, रखरखाव, और स्थिरता को चोट पहुंचाते हैं। ओपी का प्रश्न एक साधारण "वापसी" या "फेंक" के साथ हल किया जा सकता है (इस प्रकार किसी भी तरह से गेटोस पर निर्भर नहीं है)। –

+6

बिल्कुल। जब आपको लगता है कि आपको 'गोटो' की ज़रूरत है, तो पहले एक पल के लिए रुकें और सोचें कि क्या आप वास्तव में करते हैं। यदि आपको अभी भी 'गोटो' की आवश्यकता है, तो बस इसका उपयोग करें - यह किसी कारण से भाषा में है। यह स्वाभाविक रूप से बुराई नहीं है - यह आमतौर पर बुरे पैटर्न में दिखाई देता है, और इसलिए इसे रोकने के लिए सिग्नल के रूप में कार्य करना चाहिए और ऐसे पैटर्न को खोजने की कोशिश करना चाहिए (और "ओएमजी' गोटो "में डुबकी नहीं करना यह सब गलत है" आतंक)। –

+0

गोटो स्वाभाविक रूप से बुरा नहीं है, लेकिन यह खराब, आलसी कोड के लिए गेटवे दवा है। प्रवाह को नियंत्रित करने के सभी तरीकों में से, यह * आमतौर पर * सबसे खराब है। –

10

स्वैप जबकि पाश भीतरी साथ ट्राई/कैच संरचना:

while { 
    try { 
    while { 
     throw; 
    } 
    } 
    catch { 
    continue; 
    } 
} 
4

सं
मेरा सुझाव है, एक अलग विधि में भीतरी पाश निकालने।

while 
{ 
    // outer loop 
     try 
     { 
      myMethodWithWhileLoopThatThrowsException() 
     } 
     catch 
     { 
      // how do I continue on the outer loop from here? 
      continue; 
     } 
    } 
} 
+0

यह समस्याग्रस्त है क्योंकि अलग-अलग मेटोड में मौजूदा स्थानीय चर तक पहुंच नहीं होगी। – zvrba

+4

यही कारण है कि माइक्रोसॉफ्ट ने हमें फ़ंक्शन पैरामीटर दिए। – Welbog

+0

पैरामीटर के रूप में चर को पास करते हैं, या यदि दुष्प्रभाव आवश्यक हैं, तो विधि में निष्पादित करने के लिए इसे एक अज्ञात प्रतिनिधि के रूप में भेजें। फिर संकलक आपके स्थानीय दायरे को संरक्षित करते हुए बंद कर देगा। –

18

आप ब्रेक का उपयोग कर सकते हैं; बयान।

while 
{ 
    while 
    { 
     try 
     { 
      throw; 
     } 
     catch 
     { 
      break; 
     } 
    } 
} 

जारी रखें वर्तमान लूप के शीर्ष पर वापस कूदने के लिए उपयोग किया जाता है।

यदि आपको उससे अधिक स्तर तोड़ने की ज़रूरत है तो आपको या तो किसी प्रकार का 'अगर' जोड़ना होगा या ड्रेडेड/अनुशंसित 'गोटो' का उपयोग करना होगा।

+2

के लिए अपवाद हैंडलिंग प्रक्रिया का भी उपयोग नहीं करना चाहिए, इस विधि के साथ समस्या यह है कि आंतरिक लूप के अंत और बाहरी पाश के अंत के बीच अतिरिक्त कार्य करने की आवश्यकता है, तो यह होगा 'ब्रेक 'कॉल करते समय किया जाना चाहिए, लेकिन' जारी रखें 'कॉल करते समय नहीं किया जाएगा। यदि आपको उस कोड को निष्पादित करने की आवश्यकता नहीं है तो आपको ध्वज की आवश्यकता होगी। मैं यह नहीं कह रहा हूं कि यह जवाब गलत है (बिल्ली, मैंने इसे ऊपर उठाया), मैं कह रहा हूं कि यह भ्रामक रूप से सरल है। – Welbog

2

आंतरिक लूप में break का उपयोग करें।

1

आप केवल उस आंतरिक से तोड़ना चाहते हैं जो बाहरी जारी रखेगा।

while 
{ 
    // outer loop 

    while 
    { 
     // inner loop 
     try 
     { 
      throw; 
     } 
     catch 
     { 
      // how do I continue on the outer loop from here? 
      break; 
     } 
    } 
} 
0

मैं सबसे अच्छा तरीका यह है, तोड़ कथन का उपयोग करने के लिए किया जाएगा लगता है। ब्रेक वर्तमान लूप और समाप्त होता है जहां से यह समाप्त होता है। इस मामले में, यह आंतरिक लूप और समाप्त हो जाएगा जबकि लूप बाहरी में वापस कूदें। यह आपका कोड जैसा दिखता है:

while 
{ 
    // outer loop 

    while 
    { 
     // inner loop 
     try 
     { 
      throw; 
     } 
     catch 
     { 
      // break jumps to outer loop, ends inner loop immediately. 
      break; //THIS IS THE BREAK 
     } 
    } 
} 

मुझे विश्वास है कि आप जो हासिल करना चाहते थे, सही है? धन्यवाद!

-2

अपने स्वयं के अपवाद प्रकार का उपयोग करें, उदाहरण के लिए, MyException। फिर:

while 
{ 
    try { 
    // outer loop 
    while 
    { 
     // inner loop 
     try 
     { 
      throw; 
     } 
     catch 
     { 
      // how do I continue on the outer loop from here? 
      throw MyException; 
     } 
    } 
    } catch(MyException) 
    { ; } 
} 

यह बयान के दौरान नेस्टेड के कई स्तरों को जारी रखने और तोड़ने के लिए काम करेगा। बुरा स्वरूपण के लिए खेद है;)

+4

आप अपवादों का उपयोग करके मेरी भावनाओं को चोट पहुंचाते हैं प्रवाह नियंत्रण से कोई अन्य उद्देश्य नहीं। कोई डाउनवोट नहीं, केवल भावनाओं को चोट पहुंचाएं।:( –

+3

यह मुझे हर जगह उल्टी करना चाहता है –

+2

यह मेरी भावनाओं को चोट पहुंचाने से थोड़ा अधिक जबरदस्त है। –

22
while 
    { 
     // outer loop 

     while 
     { 
      // inner loop 
      try 
      { 
       throw; 
      } 
      catch 
      { 
       // how do I continue on the outer loop from here? 
       goto REPEAT; 
      } 
     } 
     // end of outer loop 
REPEAT: 
     // some statement or ; 
    } 

समस्या को हल किया। (क्या ?? तुम मुझे वह गंदे देखो क्यों दे रहे हो?)

+1

मैं देखता हूं कि आपने वहां क्या किया – Mastenka

+2

संकलित नहीं हो सकता है जब तक कि आप स्पष्ट रूप से खाली नहीं जोड़ते कथन अर्धविराम ('रेपेट:; ') – matpop

0
using System; 

namespace Examples 
{ 

    public class Continue : Exception { } 
    public class Break : Exception { } 

    public class NestedLoop 
    { 
     static public void ContinueOnParentLoopLevel() 
     { 
      while(true) 
      try { 
       // outer loop 

       while(true) 
       { 
        // inner loop 

        try 
        { 
         throw new Exception("Bali mu mamata"); 
        } 
        catch (Exception) 
        { 
         // how do I continue on the outer loop from here? 

         throw new Continue(); 
        } 
       } 
      } catch (Continue) { 
        continue; 
      } 
     } 
    } 

} 

}