स्विच स्टेटमेंट फॉल-थ्रू… इसकी अनुमति दी जानी चाहिए? [बन्द है]


120

जब तक मुझे याद है मैं स्विच स्टेटमेंट फॉल-थ्रू का उपयोग करने से बचता हूं। वास्तव में, मैं इसे कभी भी अपनी चेतना में प्रवेश नहीं कर सकता कि चीजों को करने का एक संभव तरीका है क्योंकि यह मेरे सिर में जल्दी ही ड्रिल किया गया था कि यह स्विच स्टेटमेंट में बग से ज्यादा कुछ नहीं था। हालाँकि, आज मैं कुछ ऐसे कोड भर गया, जो इसे डिज़ाइन द्वारा उपयोग करता है, जिसने मुझे तुरंत आश्चर्य में डाल दिया कि समुदाय में हर कोई स्विच स्टेटमेंट फ़ॉल-थ्रू के बारे में क्या सोचता है।

क्या यह कुछ ऐसा है जिसे प्रोग्रामिंग भाषा को स्पष्ट रूप से अनुमति नहीं देनी चाहिए (जैसे C # करता है, हालांकि यह वर्कअराउंड की आपूर्ति करता है) या क्या यह किसी भी भाषा की विशेषता है जो प्रोग्रामर के हाथों में छोड़ने के लिए पर्याप्त शक्तिशाली है?

संपादित करें: मैं इस बात से विशिष्ट नहीं था कि मेरा मतलब क्या है। मैं इस प्रकार का बहुत उपयोग करता हूं:

    switch(m_loadAnimSubCt){
        case 0:
        case 1:
            // Do something
            break;
        case 2:
        case 3:
        case 4:
            // Do something
            break;
   }

हालाँकि, मैं कुछ इस तरह के बारे में चिंतित हूँ।

   switch(m_loadAnimSubCt){
        case 0:
        case 1:
            // Do something, but fall through to the other cases
            // after doing it.

        case 2:
        case 3:
        case 4:
            // Do something else.
            break;
   }

इस तरह जब भी मामला 0 है, 1 यह स्विच स्टेटमेंट में सब कुछ करेगा। मैंने इसे डिजाइन द्वारा देखा है और मुझे नहीं पता कि क्या मैं सहमत हूं कि स्विच स्टेटमेंट का इस तरह से उपयोग किया जाना चाहिए। मुझे लगता है कि पहला कोड उदाहरण एक बहुत ही उपयोगी और सुरक्षित है। दूसरी तरह की खतरनाक लगती है।



51
रचनात्मक के बारे में असहमत हैं। सवाल पर 27 upvotes कहते हैं कि इस तरह से महसूस करने वाले अन्य भी हैं।
वेस मोड्स

2
"रचनात्मक नहीं" एक पुराना और कुछ हद तक अस्पष्ट कारण है। आजकल, विशुद्ध रूप से राय-आधारित होने के नाते इस तरह के प्रश्नों को बंद करने के लिए ध्वजांकित किया जा सकता है और होना चाहिए। SO कोड या डिज़ाइन के बारे में उत्तर देने योग्य प्रश्नों के लिए है, न कि "जो कि" समुदाय "की राय है [जो कुछ भी है] फ़ीचर X के बारे में मेरी राय के बारे में"। प्रोग्रामर। एस ई एक बेहतर फिट होगा, लेकिन फिर भी, इस तरह के एक व्यापक और राय-चालित प्रश्न का मूल्य अभी भी अत्यधिक संदिग्ध है।
अंडरस्कोर_ड

1
बहुत स्पष्ट उपयोग-मामले हैं जहां परती का उपयोग किया जाता है, इसलिए सुनिश्चित नहीं है कि यह राय आधारित क्यों होगा। मैं मानता हूं कि यह सवाल थोड़ा अस्पष्ट है, लेकिन इसे रचनात्मक रूप से बंद नहीं किया जाना चाहिए था। शायद सिर्फ एक और अधिक स्पष्ट मामला होने के लिए संपादित किया गया: "कब उपयोग किया जाता है?" जिसका स्पष्ट उत्तर है। अच्छा C ++ टेक्स्ट इस पर जाता है, यह नए कोडर्स (या अन्य भाषाओं के और भी अनुभवी कोडर्स) के लिए भ्रामक है, इसलिए SO के लिए एक अच्छा प्रश्न लगता है। दरअसल, ऐसा लगता है कि एक प्रोटोटाइप अच्छा एसओ प्रश्न है। भले ही जिस तरह से पूछा गया था वह सही नहीं था।
एरिक

जवाबों:


89

यह इस बात पर निर्भर हो सकता है कि आप क्या विचार करते हैं। मैं इस तरह की चीज़ के साथ ठीक हूँ:

switch (value)
{
  case 0:
    result = ZERO_DIGIT;
    break;

  case 1:
  case 3:
  case 5:
  case 7:
  case 9:
     result = ODD_DIGIT;
     break;

  case 2:
  case 4:
  case 6:
  case 8:
     result = EVEN_DIGIT;
     break;
}

लेकिन अगर आपके पास एक केस लेबल है जिसके बाद कोड है जो किसी अन्य केस लेबल के माध्यम से आता है, तो मैं हमेशा उस बुराई पर विचार करता हूं। शायद कॉमन कोड को किसी फंक्शन में ले जाना और दोनों जगहों से कॉल करना एक बेहतर विचार होगा।

और कृपया ध्यान दें कि मैं "बुराई" की C ++ FAQ परिभाषा का उपयोग करता हूं


मैं आपके साथ सहमत हूं: मैं आपके उदाहरण को नतीजे के रूप में नहीं मानता हूं, और अगर कोई ऐसा मामला है जहां मैं कोड के कई ब्लॉकों को निर्णायक के माध्यम से निष्पादित करना चाहता हूं, तो शायद ऐसा करने का एक बेहतर तरीका है।
डेव ड्यूप्लांटिस

10
बस "बुराई" की उस परिभाषा के लिए। मैं धन्यवाद, ;-)
जोकिम सोउर

मुझे आपकी बात सही लगी और आप सही हैं, लेकिन आपका उदाहरण वास्तव में बुरा है। किसी को भी इस तरह टेस्ट अंकों का परीक्षण नहीं करना चाहिए। वैसे भी, आपका जवाब सही है।
टिम बुथ

मामले में मामला, यह बहुत ही बात है कि सी # को अस्वीकार करता है। संभवतः एक कारण से :-)
जॉय

दुख की बात यह है कि बुराई की परिभाषा ऑफ़लाइन हो गई है
उम्मीद है कि

57

यह दोधारी तलवार है। यह कभी-कभी बहुत उपयोगी होता है, लेकिन अक्सर खतरनाक होता है।

यह कब अच्छा है? जब आप 10 मामले चाहते हैं तो सभी उसी तरह से संसाधित होते हैं ...

switch (c) {
  case 1:
  case 2:
            ... Do some of the work ...
            /* FALLTHROUGH */
  case 17:
            ... Do something ...
            break;
  case 5:
  case 43:
            ... Do something else ...
            break;
}

एक नियम जो मुझे पसंद है वह यह है कि यदि आप कभी भी कुछ करते हैं, जहां आप ब्रेक को छोड़ देते हैं, तो आपको यह स्पष्ट टिप्पणी / * FALLTHROUGH * / की आवश्यकता है जो यह दर्शाता है कि आपका इरादा था।


3
+1! मैं मानता हूं कि यह कभी-कभार ही सही उत्तर होता है, और मैं पूरी तरह से सहमत हूं कि जब यह डिजाइन द्वारा होता है, तो इसे टिप्पणी की जानी चाहिए। (एक कोड की समीक्षा में, मैं अन्य डेवलपर को गैर-रिक्त फ़ॉल-थ्रू डिज़ाइन द्वारा टिप्पणी देता हूं। ऐसा नहीं होता है; हम एक C # दुकान हैं जहां यह समर्थित नहीं है :)
जॉन रूडी

4
मैं स्वयं अपने कोड में एक / * FALL THROUGH * / टिप्पणी का उपयोग करता हूं जहां उपयुक्त हो। =]
स्ट्रैजर

2
यदि आप पीसी-लिंट करते हैं, तो आपको * * - परती * को सम्मिलित करना होगा, अन्यथा यह शिकायत करता है।
स्टीव मेलनिकॉफ़

1
फिर भी, यदि आप यह स्पष्ट करना चाहते हैं कि व्यवहार जानबूझकर किया गया है तो if(condition > 1 && condition <10) {condition = 1}; switch(...आप भी मामलों को सहेज सकते हैं (स्पष्ट रूप के लिए) और साथ ही हर कोई यह देख सकता है कि आप वास्तव में उन मामलों को उसी कार्रवाई को गति देना चाहते थे।
मार्क

1
यह अभी भी भयानक कोडिंग है। पहले मामले को किसी फ़ंक्शन को कॉल करना चाहिए, दूसरे मामले को उसी फ़ंक्शन को कॉल करना चाहिए फिर दूसरे फ़ंक्शन को कॉल करना चाहिए।
ब्लूराजा - डैनी पफ्लुगुएट

21

क्या आपने डफ डिवाइस के बारे में सुना है ? यह स्विच फ़ॉलथ्रिन का उपयोग करने का एक शानदार उदाहरण है।

यह एक ऐसी सुविधा है जिसका उपयोग किया जा सकता है और इसका दुरुपयोग किया जा सकता है, लगभग सभी भाषा सुविधाओं की तरह।


हर दिन कुछ नया सीखें - धन्यवाद! मैं उन गरीब देवों के लिए महसूस करता हूं जो हालांकि इस तरह के विरोधाभासों में जाते हैं।
जस्टिन आर।

वाह, यह काफी कुछ आपके मस्तिष्क को चारों ओर लपेटने के लिए है।
फोस्टा

6
नोट डफ की उस लेख में उद्धृत टिप्पणी: "यह कोड उस बहस में किसी प्रकार का तर्क बनाता है, लेकिन मुझे यकीन नहीं है कि इसके लिए या उसके खिलाफ है।"
जॉन कार्टर

डफ का उपकरण स्पष्ट रूप से बुराई है
मार्जेटा

21

गिरने के माध्यम से वास्तव में एक आसान बात है, आप क्या कर रहे हैं पर निर्भर करता है। विकल्पों को व्यवस्थित करने के लिए इस स्वच्छ और समझने योग्य तरीके पर विचार करें:

switch ($someoption) {
  case 'a':
  case 'b':
  case 'c':
    // Do something
    break;

  case 'd':
  case 'e':
    // Do something else
    break;
}

ऐसा करने की कल्पना करो अगर / और। यह गड़बड़ होगी।


1
मुझे लगता है कि इस प्रकार की गिरावट बहुत उपयोगी है
मिशेल सेलर्स

अगर 'कुछ करते हैं' स्विच वाइल की तुलना में सिर्फ थोड़ा अधिक है, बजाय अगर / तो गड़बड़ है। अगर / अन्यथा यह हर जगह स्पष्ट है कि किस चर का परीक्षण किया गया है। यह छोटा सा उदाहरण भी मेरी आँखों में / अन्यथा के साथ इतना बुरा नहीं लगेगा
ग्रेनेक्स

10

यह कुछ समय के लिए बहुत उपयोगी हो सकता है, लेकिन सामान्य तौर पर, कोई भी गिरावट-वांछित व्यवहार नहीं है। गिरने के माध्यम से अनुमति दी जानी चाहिए, लेकिन निहित नहीं।

एक उदाहरण, कुछ डेटा के पुराने संस्करणों को अपडेट करने के लिए:

switch (version) {
    case 1:
        // Update some stuff
    case 2:
        // Update more stuff
    case 3:
        // Update even more stuff
    case 4:
        // And so on
}

6

मुझे स्विच में कुछ कमियों के लिए एक अलग वाक्यविन्यास पसंद होगा, कुछ ऐसा, इर्रर ।।

switch(myParam)
{
  case 0 or 1 or 2:
    // Do something;
    break;
  case 3 or 4:
    // Do something else;
    break;
}

नोट: यह पहले से ही enums के साथ संभव होगा, यदि आप झंडे का उपयोग करके अपने सभी मामलों की घोषणा करते हैं, है ना? यह इतना बुरा भी नहीं लगता है; मामले पहले से ही बहुत अच्छी तरह से आपके लिए एक हिस्सा होने चाहिए।

हो सकता है कि यह विस्तार विधियों का उपयोग करते हुए एक धाराप्रवाह इंटरफ़ेस के लिए एक अच्छा मामला (कोई सज़ा नहीं) होगा? कुछ इस तरह, इर्र ...

int value = 10;
value.Switch()
  .Case(() => { /* Do something; */ }, new {0, 1, 2})
  .Case(() => { /* Do something else */ } new {3, 4})
  .Default(() => { /* Do the default case; */ });

हालांकि यह शायद कम पठनीय है: पी


1
मुझे पहला सुझाव बहुत पसंद आया। यह बहुत अच्छी तरह से पढ़ता है और कोड की कुछ पंक्तियों को बचाता है। दूसरे ने मेरे मस्तिष्क को चारों ओर लपेटने में एक मिनट का समय लिया लेकिन समझ में आता है, लेकिन यह एक गड़बड़ है।
फोस्टा

1
हाँ, यही मैंने भी सोचा था, यह सिर्फ एक यादृच्छिक मन का गला था जिसे मैंने नीचे रखा था, मौजूदा भाषा निर्माणों का उपयोग करके स्विच करने का एक अलग तरीका खोजने के प्रयास में।
एरिक वैन ब्राकेल

इस सवाल के माध्यम से दौड़ा और मुझे वास्तव में यह पसंद है! यह कैसे पठनीयता में सुधार करने के बारे में एक विचार था, लेकिन SO ने मुझे बहु-पंक्ति टिप्पणियाँ पोस्ट नहीं करने दीं :( किसी को इसे POC के रूप में लागू करना चाहिए, लागू करने और उपयोग करने में मजेदार लगता है:
विक्टर एलियास

5

किसी भी चीज़ की तरह: यदि देखभाल के साथ प्रयोग किया जाता है, तो यह एक सुंदर उपकरण हो सकता है।

हालाँकि, मुझे लगता है कि इसका उपयोग करने के औचित्य से अधिक कमियां हैं , और आखिरकार अब इसे अनुमति नहीं देना (C #)। समस्याओं में से हैं:

  • ब्रेक को "भूलना" आसान है
  • कोड अनुचर के लिए यह हमेशा स्पष्ट नहीं होता है कि एक लटकाया गया ब्रेक जानबूझकर था

स्विच / केस फॉल-थ्रू का अच्छा उपयोग:

switch (x)
{
case 1:
case 2:
case 3:
 Do something
 break;
}

Baaaaad एक स्विच / मामले गिरावट के माध्यम से के उपयोग:

switch (x)
{
case 1:
    Some code
case 2:
    Some more code
case 3:
    Even more code
    break;
}

इसका उपयोग करके फिर से लिखा जा सकता है / अगर मेरी राय में कोई नुकसान नहीं हुआ है।

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


3
यदि () और गोटो ... का उपयोग करते हुए आप अधिकांश भाषा निर्माणों को फिर से लिख सकते हैं ... हालांकि एक स्पष्ट निर्माण को छोड़ना उचित नहीं है।
शोग

2
मुझे पता है लेकिन स्विच / केस निर्माण जो स्पष्ट रूप से "केस 1: कुछ कोड केस 2: कुछ और कोड केस 3: फाइनल ब्रेक;" का उपयोग करता है; अगर (और यदि मेरी राय है) का उपयोग करके फिर से लिखा जाना चाहिए।
स्टीफेनज

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

4

यह शक्तिशाली और खतरनाक है। गिरावट के माध्यम से सबसे बड़ी समस्या यह है कि यह स्पष्ट नहीं है। उदाहरण के लिए, यदि आप अक्सर-संपादित कोड में आते हैं, जिसमें फ़ॉल-थ्रू के साथ एक स्विच होता है, तो आप कैसे जानते हैं कि यह जानबूझकर है और बग नहीं है?

कहीं भी मैं इसका उपयोग करता हूं, मैं यह सुनिश्चित करता हूं कि यह ठीक से टिप्पणी की जाए:

switch($var) {
    case 'first':
        // Fall-through
    case 'second':
        i++;
        break;
 }

2
आशय स्पष्ट है यदि केस 'पहले' के लिए कोई कोड नहीं है। यदि आप वहां कोड करते हैं, और केस 'सेकंड' के लिए कोड भी चलाना चाहते हैं, तो टिप्पणी महत्वपूर्ण है। लेकिन मैं वैसे भी उस परिदृश्य से बचता हूँ।
जोएल कोएहॉर्न

1
@ जोएल - मैं पूरी तरह से सहमत हूं। मेरी दुकान में, हमने ऐसे मामलों में लोगों को कमेंट्स में डाल दिया है, और मुझे लगता है कि यह पठनीयता को कम करता है। अगर वहाँ कोड है, हालांकि, टिप्पणी में डाल दिया।
फ्रेड लार्सन

हमारा क्या मतलब है "स्पष्ट नहीं"। इसी कारण हम टूटते हैं; अन्य भाषाएं ऐसा करती हैं। यह केवल उन लोगों के लिए एक मुद्दा है जिन्होंने अपनी भाषाओं को क्रम में नहीं सीखा है। C # इसे डिफ़ॉल्ट केस ffs के लिए मांगता है, बिना किसी कारण के imho के साथ।
mckenzm

3

आपके पहले उदाहरण की तरह फ़ॉल-थ्रू का उपयोग करना ठीक है, और मैं इसे वास्तविक फ़ॉल-थ्रू नहीं मानूंगा।

दूसरा उदाहरण खतरनाक है और (यदि बड़े पैमाने पर टिप्पणी नहीं की गई है) गैर-स्पष्ट। मैं अपने छात्रों को ऐसे निर्माणों का उपयोग नहीं करने के लिए सिखाता हूं जब तक कि वे इसे एक टिप्पणी ब्लॉक को समर्पित करने के प्रयास के लायक नहीं समझते हैं, जो बताता है कि यह एक जानबूझकर गिरावट है, और यह समाधान विकल्पों से बेहतर क्यों है। यह मैला उपयोग को हतोत्साहित करता है, लेकिन यह अभी भी उन मामलों में इसकी अनुमति देता है जहां इसका उपयोग लाभ के लिए किया जाता है।

यह कम या ज्यादा के बराबर है जो हमने अंतरिक्ष परियोजनाओं में किया था जब कोई कोडिंग मानक का उल्लंघन करना चाहता था: उन्हें डिस्पेंस करने के लिए आवेदन करना था (और मुझे सत्तारूढ़ के बारे में सलाह देने के लिए बुलाया गया था)।


2

मुझे अपने switchबयानों के माध्यम से गिरना पसंद नहीं है - यह बहुत अधिक त्रुटि प्रवण और पढ़ने में कठिन है। जब कई एकमात्र अपवाद है caseबयानों सब करने वास्तव में एक ही बात।

यदि कुछ सामान्य कोड है जो एक स्विच स्टेटमेंट की कई शाखाओं का उपयोग करना चाहते हैं, तो मैं इसे एक अलग आम फ़ंक्शन में निकालता हूं जिसे किसी भी शाखा में कहा जा सकता है।


1

कुछ उदाहरणों में, फॉल-थ्रू का उपयोग करना प्रोग्रामर की ओर से आलस्य का एक कार्य है - वे एक श्रृंखला का उपयोग कर सकते हैं || उदाहरण के लिए, बयान, लेकिन इसके बजाय 'कैच-ऑल' स्विच मामलों की एक श्रृंखला का उपयोग करें।

कहा जा रहा है, मैंने उन्हें विशेष रूप से उपयोगी पाया है जब मुझे पता है कि आखिरकार मुझे वैसे भी विकल्पों की आवश्यकता है (उदाहरण के लिए मेनू प्रतिक्रिया में), लेकिन अभी तक सभी विकल्पों को लागू नहीं किया है। इसी तरह, यदि आप 'a ’और, A’ दोनों के लिए फॉल-थ्रू कर रहे हैं, तो मुझे स्टेटमेंट की तुलना में कंपाउंड-थ्रू स्विच का उपयोग करने के लिए पर्याप्त रूप से क्लीनर मिल जाता है।

यह शायद शैली की बात है और प्रोग्रामर कैसे सोचते हैं, लेकिन मैं आमतौर पर 'सुरक्षा' के नाम पर किसी भाषा के घटकों को हटाने का शौकीन नहीं हूं - यही कारण है कि मैं सी और उसके वेरिएंट / वंशजों की तुलना में अधिक कहता हूं, जावा। मुझे संकेत के साथ बंदर-चारों ओर सक्षम होना पसंद है और जब भी मेरे पास कोई "कारण" नहीं है।


सच पूछिये तो। स्विच स्टेटमेंट एक निर्धारित मूल्य के माध्यम से विशिष्ट कोड स्थानों के एक समूह में कूदते हैं। हालांकि संकलक ऐसी चीजों को पकड़ने की संभावना रखता है, एक श्रृंखला या बयानों पर स्विच स्टेटमेंट के लिए गति और शुद्धता मूल्य है। यदि p 0 है या p 1 है या p है 2. मुझे वास्तव में मूल्यांकन करना था कि क्या p 0 था और p 1 था, बजाय कोड में p = 2 स्थान पर कूदने के। जो p0, और p1 के समान हुआ। लेकिन, मुझे कभी उनकी जाँच नहीं करनी पड़ी।
15

1

फॉल-थ्रू का उपयोग केवल तभी किया जाना चाहिए जब इसे कोड के ब्लॉक में जंप टेबल के रूप में उपयोग किया जाए। यदि अधिक मामलों से पहले बिना शर्त विराम के साथ कोड का कोई हिस्सा है, तो सभी मामले समूहों को इस तरह से समाप्त करना चाहिए।

कुछ भी "बुराई" है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.