2011-01-01 24 views
17

मैं सी # में एक foreach पाश कैसे पुनः आरंभ कर सकते ??सी # में एक foreach पाश पुन: प्रारंभ करें?

उदाहरण के लिए:

Action a; 
foreach(Constrain c in Constrains) 
{ 
    if(!c.Allows(a)) 
    { 
     a.Change(); 
     restart; 
    } 
} 

यहाँ restartcontinue या break की तरह है, लेकिन यह शुरुआत यह एक for पाश फिर से 0 के काउंटर स्थापित करने की तरह है से foreach पुन: प्रारंभ होता ..

है सी # में संभव है?

संपादित करें: मैं मुझे मेरे वर्तमान कार्यान्वयन में एक बग (सूचकांक = 0) है, जो अन्य खोज की गई है नहीं होगा की खोज बताने के लिए दोनों Mehrdad Afshari और महेश Velaga धन्यवाद देना ..

+0

यह जानना दिलचस्प हो सकता है, जहां वास्तव में आप पुनः आरंभ इस तरह का प्रयोग करना होगा। आप एल्गोरिथ्म के कुछ प्रकार में परिवर्तनशील वस्तुओं की एक सूची का उपयोग कर रहे हैं। क्या आप उस वास्तविक समस्या को साझा कर सकते हैं जिसे आप हल करने का प्रयास कर रहे हैं? –

+0

वास्तविक समस्या: कुछ माहौल में ले जाने का प्रयास एजेंट। एनवी में बाधाएं हैं। बाद प्रत्येक एजेंट का फैसला करता है कि आगे क्या गति कार्रवाई है, पर्यावरण जांच करता है कि एजेंट बाधा को पार करता है, तो हाँ, पर्यावरण एजेंट एक और कार्रवाई चुनने की अनुमति देता होगा; और यहां जहां मुझे नई चयनित कार्रवाई के साथ सभी बाधाओं को फिर से जांचने के लिए फ़ोरैच लूप को पुनरारंभ करने की आवश्यकता है .. मुझे उम्मीद है कि यह स्पष्ट हो जाएगा ... – Betamoo

उत्तर

53

उपयोग अच्छे पुराने goto चाहते :

restart: 
foreach(Constrain c in Constrains) 
{ 
    if(!c.Allows(a)) 
    { 
     a.Change(); 
     goto restart; 
    } 
} 

आप किसी कारण (जो नहीं एक कारण के बिना एक अच्छी बात है) के लिए समय की gotophobia 100% के साथ का निदान कर रहे हैं, आप के बजाय एक ध्वज का उपयोग कर की कोशिश कर सकते हैं:

bool restart; 
do { 
    restart = false; 
    foreach(Constrain c in Constrains) 
    { 
     if(!c.Allows(a)) 
     { 
     a.Change(); 
     restart = true; 
     break; 
     } 
    } 
} while (restart); 
+3

+1 मुझे आपके डू लूप कार्यान्वयन पसंद है। –

+8

गेटोस के साथ सावधान रहें http://xkcd.com/292/ – digEmAll

+1

सावधान रहें! dotnet3.5 और उससे परे (LINQ आदि) में, foreach() एक बंद करने में खींच सकते हैं। यह समाधान, या लूप से बाहर निकलने वाला कोई अन्य, बंद होने का सही ढंग से निपटान करेगा। लेकिन इसके माध्यम से सोचो; यह ऐसी जगह है जहां सावधानीपूर्वक डिज़ाइन बहुत सारे डिबगिंग को बचाएगा। –

4
void Main() 
{ 
    IEnumerable<Constrain> cons; 
    SomeObject a; 

    while(!TryChangeList(cons, a)) { } 
} 

// the name tryChangeList reveals the intent that the list will be changed 
private bool TryChangeList(IEnumerable<Constrain> constrains, SomeObject a) 
{ 
    foreach(var con in constrains) 
    { 
     if(!c.Allows(a)) 
     { 
      a.Change(); 
      return false; 
     } 
    } 
    return true; 
} 
+0

+1। रिफैक्टरिंग आमतौर पर इस तरह के मामलों में एक अच्छा समाधान है यदि यह व्यवहार्य है और चीजों को और अधिक जटिल नहीं बनाता है। –

+1

-1 क्या होगा यदि यह 'IList ' नहीं है? –

+0

@ जॉन - यह आईनेमरेबल के लिए भी काम करेगा, यदि आप आईएलआईएन को आईएनयूमेरेबल –

8

एक तरह से आप ऐसा कर सकते के लिए उपयोग कर रहा है, जैसा कि आप पहले से ही उल्लेख किया है:

पुनः आरंभ यहां जारी रखने या तोड़ने की तरह है, लेकिन यह शुरुआत यह की तरह है से foreach के पुनः प्रारंभ फिर 0 पर पाश के लिए एक काउंटर की स्थापना

Action a; 
for(var index = 0; index < Constratins.Count; index++) 
{ 
    if(!Constraints[index].Allows(a)) 
    { 
     a.Change(); 
     index = -1; // restart 
    } 
} 
+7

यह गलत है। 'index = -1' काम करेगा, अगर गणना करने योग्य सूचकांक-पहुंच योग्य है लेकिन उस स्थिति में भी, यह कोड को पढ़ने के लिए कठिन बनाता है और इरादा अस्पष्ट बनाता है। यह अंधा गोटोफोबिया के परिणामस्वरूप चीजों को और खराब बनाने का एक आदर्श उदाहरण है। कम से कम, 'गोटो' के साथ, इरादा पूरी तरह स्पष्ट है। –

+0

+1 यह पहला समाधान है जो दिमाग में आया - लूप का उपयोग क्यों नहीं करें? एक bastardized foreach समाधान क्यों बनाएँ। –

+0

@ मेहरदाद: सूचकांक भाग को सही किया। धन्यवाद –

0
for (var en = Constrains.GetEnumerator(); en.MoveNext();) 
{ 
    var c = en.Current; 
    if (!c.Allows(a)) 
    { 
     a.Change(); 
     en = Constrains.GetEnumerator(); 
    } 
} 
+4

आप मूल को पहले निपटाना चाहते हैं। –

+3

@ जॉन: दरअसल। और आपको संभावित अपवादों से निपटना होगा, जो अंततः 'उपयोग' कथन का कारण बनता है, और उस समय, आपको एहसास होगा कि आपको पहले स्थान पर 'foreach' को छूना नहीं चाहिए था! –

8
हालांकि एक बहुत पुरानी धागा

- कि कोड के शब्दों की वजह से ध्यान दिया जवाब में से कोई भी: a

  • तो a टूट जाता है पर

    • आप बाधाओं की एक श्रृंखला है उनमें से किसी को, एक और a कोशिश और श्रृंखला के माध्यम से धक्का।

    है, a.Change() बाधा जाँच पाश से अलग किया जाना चाहिए, यह भी CQS सिद्धांत का पालन:

    while (!MeetsConstraints(a)) 
    { 
        a.Change(); 
    } 
    
    bool MeetsConstraints(Thing a) 
    { 
        return Constraints.All(c => c.Allows(a)); 
    } 
    

    नहीं गोटो, कोई बदसूरत छोरों, बस सरल और साफ। </स्व-बैक-थप्पड़ मारने >

  • संबंधित मुद्दे