रिटर्न के साथ स्टेटमेंट स्विच करें - कोड शुद्धता


90

मान लीजिए कि इस संरचना के साथ C में मेरा कोड है:

switch (something)
{
    case 0:
      return "blah";
      break;

    case 1:
    case 4:
      return "foo";
      break;

    case 2:
    case 3:
      return "bar";
      break;

    default:
      return "foobar";
      break;
}

अब जाहिर है, breakकोड को सही ढंग से चलाने के लिए एस आवश्यक नहीं हैं, लेकिन यह बुरी तरह से अभ्यास की तरह दिखता है अगर मैं उन्हें वहां नहीं रखता हूं।

तुम क्या सोचते हो? क्या उन्हें हटाना ठीक है? या आप उन्हें "शुद्धता" बढ़ाने के लिए रखेंगे?

जवाबों:


136

breakस्टेटमेंट निकालें । उन्हें जरूरत नहीं है और शायद कुछ संकलक "अप्राप्य कोड" चेतावनी जारी करेंगे ।


2
वही अन्य बिना शर्त नियंत्रण-कूदने वाले कथनों के साथ लागू होता है, जैसे continueया goto- इसके स्थान पर उनका उपयोग करना मुहावरेदार है break
कैफे

31

मैं पूरी तरह से अलग तरह का सौदा करूंगा। विधि / कार्य के बीच में RETURN न करें। इसके बजाय, बस एक स्थानीय चर में वापसी मूल्य डालें और इसे अंत में भेजें।

व्यक्तिगत रूप से, मुझे निम्नलिखित अधिक पठनीय लगता है:

String result = "";

switch (something) {
case 0:
  result = "blah";
  break;
case 1:
  result = "foo";
  break;
}

return result;

23
"वन एक्जिट" दर्शन सी में समझ में आता है, जहां आपको यह सुनिश्चित करने की आवश्यकता है कि चीजों को सही ढंग से साफ किया जाए। सी ++ में ध्यान में रखते हुए आप किसी भी बिंदु पर एक अपवाद से फ़ंक्शन से बाहर निकाल सकते हैं, एक निकास दर्शन वास्तव में सी ++ में उपयोगी नहीं है।
बिली ओनली

29
सिद्धांत रूप में यह एक महान विचार है, लेकिन इसमें अक्सर अतिरिक्त नियंत्रण ब्लॉकों की आवश्यकता होती है जो पठनीयता को बाधित कर सकते हैं।
मिकेरोबी

8
प्राथमिक कारण कि मैं इस तरह से काम करता हूं, वह यह है कि लंबे कार्यों में कोड के माध्यम से स्कैन करते समय एक्जिट वेक्टर को याद करना बहुत आसान है। हालांकि, जब निकास हमेशा अंत में होता है तो यह जल्दी से पकड़ना आसान होता है कि क्या हो रहा है।
NotMe

7
ठीक है, कि, और कोड के बीच में ब्लॉक लौटें बस मुझे GOTO दुरुपयोग की याद दिलाता है।
NotMe

5
@ क्रिस: लंबे कार्यों में, मैं पूरी तरह से सहमत हूं - लेकिन यह आमतौर पर बड़ी समस्याओं के लिए बोलता है, इसलिए इसे बाहर निकाल दें। कई मामलों में, यह एक तुच्छ फ़ंक्शन है जो स्विच पर लौट रहा है, और यह बहुत स्पष्ट है कि क्या होना चाहिए, इसलिए एक अतिरिक्त चर को ट्रैक करने पर मस्तिष्क की शक्ति को बर्बाद न करें।
स्टीफन

8

व्यक्तिगत रूप से मैं रिटर्न निकालूंगा और ब्रेक लगाता रहूंगा। मैं एक वैरिएबल को मान असाइन करने के लिए स्विच स्टेटमेंट का उपयोग करूंगा। फिर स्विच स्टेटमेंट के बाद उस वेरिएबल को लौटा दें।

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

एक अपवाद: यदि किसी संसाधन के अधिग्रहण से पहले खराब पैरामीटर का पता लगाया जाता है, तो जल्दी लौटना ठीक है।


इस विशेष के लिए अच्छा हो सकता है switch, लेकिन जरूरी नहीं कि सामान्य रूप से सबसे अच्छा हो। खैर, मान लें कि एक फ़ंक्शन के अंदर स्विच स्टेटमेंट कोड की एक और 500 लाइनों से पहले होता है जो केवल तभी मान्य होता है जब कुछ मामले होते हैं true। उन सभी अतिरिक्त मामलों को निष्पादित करने की क्या बात है, जिन्हें निष्पादित करने की आवश्यकता नहीं है; यह सिर्फ उन लोगों returnके switchलिए अंदर बेहतर नहीं है case?
Fr0zenFyr

6

विराम रखें - यदि आप पहले से ही विराम लगा रहे हैं तो कोड को बाद में संपादित करने पर / यदि आप कोड को संपादित करते हैं, तो आप मुश्किल में पड़ सकते हैं।

एक समारोह के बीच से लौटने के लिए बुरा व्यवहार करने के लिए बहुत से लोगों ने (मेरे सहित) माना है। आदर्श रूप से एक फ़ंक्शन में एक प्रवेश बिंदु और एक निकास बिंदु होना चाहिए।


5

उन्हें हटा दो। यह caseबयानों से लौटने के लिए मुहावरेदार है , और यह अन्यथा "अगम्य कोड" शोर है।


5

मैं उन्हें हटा दूंगा। मेरी पुस्तक में, उस तरह के मृत कोड को त्रुटियों के रूप में माना जाना चाहिए क्योंकि यह आपको एक डबल-टेक करता है और अपने आप से पूछता है "मैं उस रेखा को कभी कैसे निष्पादित करूंगा?"


4

मैं आम तौर पर उनके बिना कोड लिखूंगा। IMO, डेड कोड धीमेपन और / या समझ की कमी को दर्शाता है।

बेशक, मैं भी कुछ इस तरह पर विचार करेंगे:

char const *rets[] = {"blah", "foo", "bar"};

return rets[something];

संपादित करें: संपादित पोस्ट के साथ भी, यह सामान्य विचार ठीक काम कर सकता है:

char const *rets[] = { "blah", "foo", "bar", "bar", "foo"};

if ((unsigned)something < 5)
    return rets[something]
return "foobar";

कुछ बिंदु पर, खासकर यदि इनपुट मान विरल हैं (उदाहरण के लिए, 1, 100, 1000 और 10000), तो आप इसके बजाय विरल सरणी चाहते हैं। आप इसे या तो पेड़ या नक्शे के रूप में अच्छी तरह से लागू कर सकते हैं (हालांकि, ज़ाहिर है, एक स्विच अभी भी इस मामले में भी काम करता है)।


इस समाधान को अच्छी तरह से काम नहीं करने के लिए पोस्ट को संपादित किया।
हॉबीसॉफ्ट

@ आपका संपादन संपादित करें: हां, लेकिन यह अधिक मेमोरी लेगा, आदि। IMHO स्विच सबसे सरल तरीका है, जो कि मैं इस तरह के एक छोटे से कार्य में चाहता हूं (यह सिर्फ स्विच करता है)।
२०:०५ पर

3
@ संदेह: यह निष्कर्ष निकालने से पहले ध्यान से देखें कि यह अतिरिक्त मेमोरी लेगा। एक ठेठ संकलक के साथ, दो बार (उदाहरण के लिए) "फू" का उपयोग करके डेटा के एकल ब्लॉक में दो पॉइंटर्स का उपयोग किया जाएगा, डेटा की प्रतिकृति नहीं। आप छोटे कोड की भी उम्मीद कर सकते हैं। जब तक आपके पास बार-बार बहुत अधिक मूल्य नहीं होते हैं, तो यह अक्सर स्मृति को समग्र रूप से बचाएगा।
जेरी कॉफिन

सच। मैं अभी भी अपने समाधान पर टिकूंगा क्योंकि मूल्यों की सूची बहुत लंबी है, और एक स्विच बस अच्छा लग रहा है।
२१:०२ पर

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

2

मैं कहूंगा कि उन्हें हटा दें और एक डिफ़ॉल्ट: शाखा को परिभाषित करें।


यदि कोई समझदार डिफ़ॉल्ट नहीं है, तो आपको डिफ़ॉल्ट को परिभाषित नहीं करना चाहिए।
बिली ओनली

एक है, और मैंने एक को परिभाषित किया है, मैंने अभी इसे प्रश्न में नहीं डाला है, इसे अभी संपादित किया है।
१10

2

क्या इसके साथ एक सरणी रखना बेहतर नहीं होगा

arr[0] = "blah"
arr[1] = "foo"
arr[2] = "bar"

और क्या return arr[something];?

यदि यह सामान्य रूप से अभ्यास के बारे में है, तो आपको breakबयानों को स्विच में रखना चाहिए । इस घटना में कि आपको returnभविष्य में बयानों की आवश्यकता नहीं है , यह अगले के माध्यम से गिरने की संभावना को कम करता है case


इस समाधान को अच्छी तरह से काम नहीं करने के लिए पोस्ट को संपादित किया।
हॉबीसॉफ्ट

2

"शुद्धता" के लिए, एकल प्रवेश, एकल निकास ब्लॉक एक अच्छा विचार है। कम से कम वे तब थे जब मैंने अपनी कंप्यूटर साइंस की डिग्री ली थी। इसलिए मैं शायद एक चर घोषित करूंगा, इसे स्विच में असाइन करूंगा और फ़ंक्शन के अंत में एक बार वापस आऊंगा


2

तुम क्या सोचते हो? क्या उन्हें हटाना ठीक है? या आप उन्हें "शुद्धता" बढ़ाने के लिए रखेंगे?

इन्हें हटाना ठीक है। का उपयोग करना return है वास्तव में परिदृश्य में जहाँ breakनहीं किया जाना चाहिए।


1

दिलचस्प। इन उत्तरों में से अधिकांश से सर्वसम्मति से प्रतीत होता है कि निरर्थक breakबयान अनावश्यक अव्यवस्था है। दूसरी ओर, मैंने breakएक स्विच में एक मामले के 'समापन' के रूप में बयान पढ़ा । caseब्लॉक जो एक में समाप्त नहीं होते हैंbreak संभावित गिरावट के रूप में मुझ पर कूदने के लिए प्रवृत्ति होते हैं, हालांकि बग।

मुझे पता है कि ऐसा नहीं है जब यह एक के returnबजाय है break, लेकिन यह है कि कैसे मेरी आँखें एक स्विच में 'केस' को पढ़ती हैं, इसलिए मैं व्यक्तिगत रूप से पसंद करूंगा कि प्रत्येक caseको एक के साथ जोड़ा जाए break। लेकिन कई कंपाइलर breakएक के बाद शिकायत करते हैंreturn अत्यधिक / अप्राप्य होने के , और जाहिर है मैं वैसे भी अल्पमत में हूं।

तो breakनिम्नलिखित से छुटकारा पाएं एreturn

NB: यह सब अनदेखा कर रहा है कि एकल प्रविष्टि / निकास नियम का उल्लंघन करना एक अच्छा विचार है या नहीं। जहां तक ​​यह जाता है, मेरी राय है कि दुर्भाग्य से परिस्थितियों के आधार पर परिवर्तन होता है ...


0

मैं कहता हूं उन्हें हटा दो। यदि आपका कोड इतना अपठनीय है कि आपको 'सुरक्षित स्थान पर रहने के लिए' वहां स्टिक को चिपकाने की आवश्यकता है, तो आपको अपनी कोडिंग शैली पर पुनर्विचार करना चाहिए :)

इसके अलावा मैं हमेशा स्विच स्टेटमेंट में ब्रेक और रिटर्न को मिक्स नहीं करना पसंद करता हूं, बल्कि उनमें से एक के साथ रहना पसंद करता हूं।


0

मैं व्यक्तिगत रूप से breaks को खो देता हूं । संभवतः इस आदत का एक स्रोत विंडोज ऐप्स के लिए प्रोग्रामिंग विंडो प्रक्रियाओं से है:

LRESULT WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
        case WM_SIZE:
            return sizeHandler (...);
        case WM_DESTROY:
            return destroyHandler (...);
        ...
    }

    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

मैं व्यक्तिगत रूप से इस दृष्टिकोण को प्रत्येक हैंडलर द्वारा दिए गए रिटर्न वैरिएबल की घोषणा करने की तुलना में बहुत सरल, रसीला और लचीला पाता हूं, फिर इसे अंत में लौटाता हूं। इस दृष्टिकोण को देखते हुए, breakएस निरर्थक हैं और इसलिए उन्हें जाना चाहिए - वे कोई उपयोगी उद्देश्य (वाक्यगत या IMO नेत्रहीन) नहीं देते हैं और केवल कोड को ब्लोट करते हैं।


0

मुझे लगता है कि * ब्रेक एक उद्देश्य के लिए * एस हैं। यह प्रोग्रामिंग की ide विचारधारा ’को जीवित रखना है। यदि हम तार्किक सामंजस्य के बिना हमारे कोड को केवल 'प्रोग्राम' कर रहे हैं तो शायद यह आपके लिए अब पढ़ने योग्य होगा, लेकिन कल प्रयास करें। इसे अपने बॉस को समझाने की कोशिश करें। इसे विंडोज 3030 पर चलाने का प्रयास करें।

हाँ, यह विचार बहुत सरल है:


Switch ( Algorithm )
{

 case 1:
 {
   Call_911;
   Jump;
 }**break**;
 case 2:
 {
   Call Samantha_28;
   Forget;
 }**break**;
 case 3:
 {
   Call it_a_day;
 }**break**;

Return thinkAboutIt?1:return 0;

void Samantha_28(int oBed)
{
   LONG way_from_right;
   SHORT Forget_is_my_job;
   LONG JMP_is_for_assembly;
   LONG assembly_I_work_for_cops;

   BOOL allOfTheAbove;

   int Elligence_says_anyways_thinkAboutIt_**break**_if_we_code_like_this_we_d_be_monkeys;

}
// Sometimes Programming is supposed to convey the meaning and the essence of the task at hand. It is // there to serve a purpose and to keep it alive. While you are not looking, your program is doing  // its thing. Do you trust it?
// This is how you can...
// ----------
// **Break**; Please, take a **Break**;

/ * बस एक मामूली सवाल है, हालांकि। उपरोक्त पढ़ते हुए आपके पास कितनी कॉफी है? आईटी प्रणाली कभी-कभी टूट जाती है * /


0

एक बिंदु पर कोड से बाहर निकलें। यह कोड को बेहतर पठनीयता प्रदान करता है। बीच में रिटर्न स्टेटमेंट (एकाधिक निकास) जोड़ना डिबगिंग को कठिन बना देगा।


0

यदि आपके पास "लुकअप" प्रकार का कोड है, तो आप स्विच-केस क्लॉज को एक विधि द्वारा पैकेज कर सकते हैं।

मेरे पास "शौक" प्रणाली में इनमें से कुछ हैं जो मैं मनोरंजन के लिए विकसित कर रहा हूं:

private int basePerCapitaIncomeRaw(int tl) {
    switch (tl) {
        case 0:     return 7500;
        case 1:     return 7800;
        case 2:     return 8100;
        case 3:     return 8400;
        case 4:     return 9600;
        case 5:     return 13000;
        case 6:     return 19000;
        case 7:     return 25000;
        case 8:     return 31000;
        case 9:     return 43000;
        case 10:    return 67000;
        case 11:    return 97000;
        default:    return 130000;
    }
}

(हां। यह GURPS स्पेस है ...)

मैं दूसरों से सहमत हूं कि आपको ज्यादातर मामलों में एक विधि में एक से अधिक रिटर्न से बचना चाहिए, और मैं यह मानता हूं कि यह एक सरणी या कुछ और के रूप में बेहतर तरीके से लागू किया गया हो सकता है। मुझे बस स्विच-केस-रिटर्न मिला, लुकअप टेबल के लिए इनपुट और आउटपुट के बीच 1-1 सहसंबंध के साथ एक बहुत ही आसान मैच होना चाहिए, जैसे ऊपर की बात (भूमिका-खेल खेल उनमें से भरे हुए हैं, मुझे यकीन है कि वे अन्य में मौजूद हैं "व्यवसायों" के रूप में अच्छी तरह से): डी

दूसरी ओर, यदि केस-क्लॉज़ अधिक जटिल है, या स्विच-स्टेटमेंट के बाद कुछ होता है, तो मैं इसमें रिटर्न का उपयोग करने की सलाह नहीं दूंगा, बल्कि स्विच में एक चर सेट कर सकता हूं, इसे एक ब्रेक के साथ समाप्त कर दूंगा, और वापस आऊंगा अंत में चर का मूल्य।

(तीसरे ... हाथ पर ... आप हमेशा अपने स्वयं के तरीके में एक स्विच को रिफ्लेक्टर कर सकते हैं ... मुझे संदेह है कि इसका प्रदर्शन पर प्रभाव पड़ेगा, और यह मुझे आश्चर्यचकित नहीं करेगा अगर आधुनिक कंपाइलर इसे भी पहचान सकते हैं कुछ है कि इनलेट किया जा सकता है ...)

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