स्विच स्टेटमेंट में हमेशा एक डिफ़ॉल्ट क्लॉज होना चाहिए?


254

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

  1. क्या हमेशा एक डिफ़ॉल्ट बयान सहित एक समझदार कारण है?

  2. क्या यह भाषा निर्भर है? मुझे याद नहीं है कि उस समय मैं किस भाषा का उपयोग कर रहा था - शायद यह कुछ भाषाओं पर लागू होता है और दूसरों के लिए नहीं?


9
यह एक बड़ी डिग्री के लिए भाषा-निर्भर होने जा रहा है
skaffman

जवाबों:


276

स्विच मामलों में लगभग हमेशा एक defaultमामला होना चाहिए ।

उपयोग करने के कारण default

1. कोई अप्रत्याशित मूल्य 'पकड़'

switch(type)
{
    case 1:
        //something
    case 2:
        //something else
    default:
        // unknown type! based on the language,
        // there should probably be some error-handling
        // here, maybe an exception
}

2. 'डिफ़ॉल्ट' कार्यों को संभालने के लिए, जहां मामले विशेष व्यवहार के लिए हैं।

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

3. आपके कोड को पढ़ने वाले किसी व्यक्ति को दिखाने के लिए कि आपने उस मामले को कवर किया है।

variable = (variable == "value") ? 1 : 2;
switch(variable)
{
    case 1:
        // something
    case 2:
        // something else
    default:
        // will NOT execute because of the line preceding the switch.
}

यह एक अति-सरल उदाहरण था, लेकिन मुद्दा यह है कि कोड पढ़ने वाले किसी को आश्चर्य नहीं होना चाहिए कि variable1 या 2 के अलावा कुछ और क्यों नहीं हो सकता है।


केवल मामले मैं नहीं उपयोग के बारे में सोच सकते हैं defaultहै जब स्विच कुछ जहां इसकी बजाय स्पष्ट हर दूसरे विकल्प खुशी से अनदेखा किया जा सकता जाँच कर रहा है

switch(keystroke)
{
    case 'w':
        // move up
    case 'a':
        // move left
    case 's':
        // move down
    case 'd':
        // move right
    // no default really required here
}

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

1
उसी समय यदि आप एक GET पैरामीटर की जाँच कर रहे हैं, तो आप हर बार एक अपवाद को नहीं छोड़ सकते हैं जब कोई उपयोगकर्ता किसी ऐसी चीज़ के लिए url बदलता है जो मान्य नहीं है: [
एंड्रयू

4
@Andrew WASD कंप्यूटर गेम कैरेक्टर मूवमेंट के लिए आम है। आपको किसी भी डिफ़ॉल्ट कार्रवाई की आवश्यकता नहीं होगी क्योंकि अन्य कुंजियों को अन्य इंटरैक्शन के लिए सौंपा जा सकता है। इस तरह के स्विच में, आंदोलन कार्यों को कॉल करने के लिए अच्छा है।
jemiloii

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

3
@virusrocks यदि आपकी स्थिति एक एनम है, तो भी आपके पास अप्रत्याशित मूल्य हो सकते हैं। उदाहरण के लिए, यदि आप एनम के लिए एक नया मान जोड़ते हैं, और एक स्विच अपडेट करना भूल जाते हैं। इसके अलावा, कुछ भाषाओं में आप एनमर्स को पूर्णांक मान असाइन कर सकते हैं। C ++ में enum MyEnum { FOO = 0, BAR = 1 }; MyEnum value = (MyEnum)2;एक वैध MyEnumउदाहरण बनता है जो FOOया के बराबर नहीं है BAR। यदि इनमें से कोई भी समस्या आपके प्रोजेक्ट में त्रुटि का कारण बनेगी, तो एक डिफ़ॉल्ट मामला आपको बहुत तेज़ी से त्रुटि खोजने में मदद करेगा, अक्सर कोई डिबगर आवश्यक नहीं है!
cdgraham

54

नहीं।

यदि कोई डिफ़ॉल्ट कार्रवाई नहीं है, तो संदर्भ मायने रखता है। क्या होगा यदि आप केवल कुछ मूल्यों पर कार्य करने की परवाह करते हैं?

एक खेल के लिए कीप्रेस पढ़ने का उदाहरण लें

switch(a)
{
   case 'w':
     // Move Up
     break;
   case 's':
     // Move Down
     break;
   case 'a':
     // Move Left
     break;
   case 'd':
     // Move Right
     break;
}

जोड़ना:

default: // Do nothing

सिर्फ समय की बर्बादी है और बिना किसी कारण के कोड की जटिलता बढ़ जाती है।


14
अच्छा उदाहरण। लेकिन वास्तव में, एक साधारण // do nothingटिप्पणी के साथ एक डिफ़ॉल्ट क्लॉज जोड़ने से यह स्पष्ट होता है कि यह 'ठीक' है यदि सभी मामलों को कवर नहीं किया गया है, जैसा कि अन्य स्विच स्टेटमेंट के विपरीत है जहां यह 'ठीक नहीं' है।
द नेल

8
नहीं, कोडिंग केवल कुछ मामलों को संभालने के बारे में नहीं है। इसके अलावा यह एक दस्तावेज के रूप में कार्य करता है। डिफ़ॉल्ट रूप से लिखने से: और जैसे // कुछ भी नहीं या कुछ और टिप्पणी करना, कोड की पठनीयता बेहतर हो जाती है।
जोंगआम पार्क

22
अन्य टिप्पणियों से असहमत हैं। डिफ़ॉल्ट जोड़ना // कुछ भी बहुत कम नहीं जोड़ा जाता है जब तक कि आपको नहीं पता कि कोड कैसे काम करता है। मैं एक डिफ़ॉल्ट के बिना एक स्विच स्टेटमेंट को देख सकता हूं और यह जान सकता हूं कि डिफ़ॉल्ट कुछ भी नहीं करना है। अव्यवस्था जोड़ने से यह अधिक स्पष्ट नहीं होता है।
राबर्ट नैक

बिल्कुल सही। यह अल पोस्ट परमेस को सौंपने की अवधारणा में है। आप दूसरों की परवाह नहीं करते हैं।
जिमी केन

2
@jybrd यदि आपको भरोसा नहीं है कि पिछले डेवलपर ने जानबूझकर डिफ़ॉल्ट को छोड़ दिया है, तो आप क्यों भरोसा करेंगे कि वे इसे डालने के लिए सही थे? एक डिफ़ॉल्ट आकस्मिक रूप से खाली हो सकता है जितना आसान पूरी तरह से गायब है। इतनी तुच्छ चीज़ के लिए एक टिप्पणी आवश्यक नहीं है। यह कोड अव्यवस्था है। इसके बजाय अपने इरादों को दिखाने के लिए पूर्ण कवरेज इकाई परीक्षण लिखें। (सिर्फ मेरी राय)
रॉबर्ट नैक

45

डिफ़ॉल्ट मामला न होना वास्तव में कुछ स्थितियों में फायदेमंद हो सकता है।

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

enum SomeEnum
{
    ENUM_1,
    ENUM_2,
    // More ENUM values may be added in future
};

int foo(SomeEnum value)
{
    switch (value)
    {
    case ENUM_1:
        return 1;
    case ENUM_2:
        return 2;
    }
    // handle invalid values here
    return 0;
 }

यह एक महत्वपूर्ण अवलोकन है! यह जावा में और भी अधिक लागू होता है क्योंकि यह आपको इनट्यूम्स को एनम को कास्ट करने की अनुमति नहीं देता है।
Lii

2
अपने उदाहरण में आप स्विच-स्टेटमेंट के बाद लौटने के बजाय एक अपवाद फेंक सकते हैं। इस तरह से आप संकलक द्वारा दोनों स्थैतिक जाँच कर सकते हैं और यदि कुछ अप्रत्याशित होता है तो स्पष्ट त्रुटि प्राप्त कर सकते हैं।
Lii

1
मैं सहमत हूँ। उदाहरण के लिए स्विफ्ट में, स्विच को संपूर्ण होना चाहिए अन्यथा आपको एक कंपाइलर त्रुटि मिलती है! डिफ़ॉल्ट प्रदान करना इस उपयोगी त्रुटि को शांत करता है। दूसरी ओर, एक डिफ़ॉल्ट प्रदान करना यदि सभी मामलों को वास्तव में संभाला जाता है तो संकलक चेतावनी (अगम्य कथन) फेंकता है।
एंडी

1
बस एक बग तय किया है, जो कि डिफ़ॉल्ट न होने पर कंपाइलर से चेतावनी का कारण होगा: इसलिए आमतौर पर एनम वेरिएबल्स पर एक स्विच को कोई डिफ़ॉल्ट नहीं होना चाहिए।
notan

42

मैं हमेशा एक डिफ़ॉल्ट क्लॉज का उपयोग करूंगा, इससे कोई फर्क नहीं पड़ता कि आप किस भाषा में काम कर रहे हैं।

चीजें गलत हो सकती हैं। मान वह नहीं होगा जो आप उम्मीद करते हैं, और इसी तरह।

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

यही कारण है कि आपको हमेशा एक डिफ़ॉल्ट क्लॉज का उपयोग करना चाहिए और जावा में उदाहरण के लिए एक त्रुटि फेंकना चाहिए:

switch (myVar) {
   case 1: ......; break;
   case 2: ......; break;
   default: throw new RuntimeException("unreachable");
}

केवल "अगम्य" स्ट्रिंग की तुलना में अधिक जानकारी शामिल करने का कोई कारण नहीं है; यदि वास्तव में ऐसा होता है, तो आपको वैसे भी स्रोत और चर आदि के मूल्यों को देखने की जरूरत है, और अपवाद स्टैकट्रेस में वह पंक्ति संख्या शामिल होगी, इसलिए अपवाद संदेश में अधिक पाठ लिखने में अपना समय बर्बाद करने की आवश्यकता नहीं है।


39
मैं पसंद करूंगा throw new RuntimeException("myVar invalid " + myVar);क्योंकि यह आपको डिबगर का उपयोग किए बिना बग को पता लगाने और ठीक करने के लिए पर्याप्त जानकारी दे सकता है और चर का निरीक्षण कर सकता है, जो कि मुश्किल हो सकता है अगर यह शायद ही कभी होने वाली समस्या है जो पुन: उत्पन्न करने के लिए कठिन है।
क्रिस डोड

1
क्या होगा यदि यह मामलों में से एक से मेल न खाने के मूल्य के लिए एक त्रुटि स्थिति नहीं है?
गबई

4
यदि यह एक त्रुटि स्थिति नहीं है, तो इसके लिए कोई आवश्यकता नहीं होगी default:। लेकिन अधिक बार ऐसा नहीं होता है, एक डिफ़ॉल्ट को छोड़ देता है क्योंकि एक सोचता है कि myVarसूचीबद्ध लोगों के अलावा कोई मूल्य नहीं हो सकता है; हालाँकि, मैं वास्तविक जीवन में आश्चर्यचकित होने की संख्या को नहीं गिन सकता, जब चर का मान "संभवतः" हो सकता है। उन मामलों में, मैं इस अपवाद के लिए आभारी हूं कि मुझे यह देखने के बजाय कि कुछ अन्य त्रुटि बाद में (डीबग करने में अधिक कठिन) या गलत उत्तर देने (परीक्षण में अनदेखी हो सकती है) के बजाय।
एड्रियन स्मिथ

2
मैं एड्रियन से सहमत हूं। असफल कठिन और जल्दी असफल।
स्लैपी

मैं AssertionErrorइसके बजाय फेंकना पसंद करता हूं RuntimeException, क्योंकि यह स्थिति एक जोरदार बताते हुए समान है जो myVarसंभाले हुए मूल्यों में से एक है। यह भी कि किसी को पकड़ने और त्रुटि को निगलने का मौका छोटा है।
फिलिप वेंडलर

15

मेरी कंपनी में, हम एवियोनिक्स और डिफेंस मार्केट के लिए सॉफ्टवेयर लिखते हैं, और हम हमेशा एक डिफ़ॉल्ट स्टेटमेंट शामिल करते हैं, क्योंकि एक स्विच स्टेटमेंट में सभी मामलों को स्पष्ट रूप से नियंत्रित किया जाना चाहिए (भले ही यह केवल एक टिप्पणी है 'कुछ भी न करें')। हम सॉफ़्टवेयर को केवल दुर्व्यवहार करने या अनपेक्षित रूप से क्रैश (या यहां तक ​​कि जिसे हम असंभव समझते हैं) मूल्यों को बर्दाश्त नहीं कर सकते।

यह चर्चा की जा सकती है कि एक डिफ़ॉल्ट मामला हमेशा आवश्यक नहीं होता है, लेकिन हमेशा इसकी आवश्यकता होती है, यह हमारे कोड एनालाइज़र द्वारा आसानी से जांचा जाता है।


1
मेरी वही आवश्यकता है जहाँ मैं काम करता हूँ; हम एम्बेडेड ontControllers के लिए कोड लिखते हैं जिन्हें सख्त सुरक्षा जांच से गुजरना पड़ता है और अक्सर EMI के अधीन होते हैं। यह मान लेना गैरजिम्मेदार होगा कि एन्यूमरेटेड वैरिएबल का मान कभी नहीं होगा जो एन्यूमरेशन लिस्ट में नहीं है।
ओस्टरवाल

12

क्या "स्विच" कथन में हमेशा एक डिफ़ॉल्ट क्लॉज शामिल होना चाहिए ? यह चाहिए आम तौर पर एक डिफ़ॉल्ट शामिल ।

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

यहाँ एक तुच्छ उदाहरण है जहाँ इसका कोई अर्थ नहीं है:

void PrintSign(int i)
{
    switch (Math.Sign(i))
    {
    case 1:
        Console.Write("positive ");
        break;
    case -1:
        Console.Write("negative ");
        break;
    default: // useless
    }
    Console.Write("integer");
}

यह इसके बराबर है:

void PrintSign(int i)
{
    int sgn = Math.Sign(i);
    if (sgn == 1)
        Console.Write("positive ");
    else if (sgn == -1)
        Console.Write("negative ");
    else // also useless
    {
    }
    Console.Write("integer");
}

मैं असहमत हूं। IMHO, एक ही समय में एक डिफ़ॉल्ट मौजूद नहीं होना चाहिए, अगर कोई रास्ता नहीं है, अभी और हमेशा के लिए, कि इनपुट का सेट बदल सकता है, और आपको हर संभव मूल्य मिला है। मेरे द्वारा सोचा जा सकने वाला सबसे सरल मामला एक डेटाबेस से बूलियन मान है, जहां केवल उत्तर (SQL परिवर्तन तक!) सही, गलत और NULL हैं। किसी भी अन्य मामले में, "नहीं होना चाहिए!" अच्छी समझ है। यदि आपका कोड बदलता है, और आपके पास एक या अधिक नए मूल्य हैं, तो आप उनके लिए कोड सुनिश्चित कर सकते हैं, और यदि आप नहीं करते हैं तो आपके परीक्षण उड़ जाएंगे।
हार्पर शेल्बी

4
@ हैपर: आपका उदाहरण "एक त्रुटि स्थिति का दावा" की श्रेणी में आता है।
गबई

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

@ हैपर: ठीक है, मैंने यह संकेत देने के लिए कि क्या कुछ भी कम नहीं है, संकेत को बदल दिया है।
गाबे

4
मुझे लगता है default:कि उन मामलों में एक आपकी मान्यताओं को संहिताबद्ध करता है। उदाहरण के लिए, क्या यह ठीक है कि कब sgn==0प्रिंट करना है integer(न तो सकारात्मक और न ही नकारात्मक), या क्या यह त्रुटि है? मेरे लिए उस कोड को पढ़ना, कहना मुश्किल है। मुझे लगता है कि आप zeroउस मामले में नहीं लिखना चाहते हैं integer, और प्रोग्रामर ने यह अनुमान sgnलगाया है कि यह केवल -1 या +1 हो सकता है। यदि ऐसा default:होता , तो प्रोग्रामर को अनुमान त्रुटि को जल्दी पकड़ने और कोड बदलने की अनुमति देता।
एड्रियन स्मिथ

7

जहाँ तक मैं देख रहा हूँ कि यह उत्तर 'डिफ़ॉल्ट' वैकल्पिक है, यह कहना कि एक स्विच में हमेशा एक डिफ़ॉल्ट होना चाहिए, यह कहने की तरह है कि यदि हर 'if -ifif' में 'और' होना चाहिए। यदि डिफ़ॉल्ट रूप से तर्क किया जाना है, तो 'डिफ़ॉल्ट' स्टेटमेंट होना चाहिए, लेकिन अन्यथा कोड कुछ भी किए बिना निष्पादित कर सकता है।


6

डिफ़ॉल्ट क्लॉज होने के बाद जब इसकी वास्तव में जरूरत नहीं होती है तो डिफेंसिव प्रोग्रामिंग यह आमतौर पर कोड की ओर जाता है जो बहुत ज्यादा एरर हैंडलिंग कोड के कारण अत्यधिक जटिल होता है। यह त्रुटि हैंडलिंग और डिटेक्शन कोड कोड की पठनीयता को परेशान करता है, रखरखाव को कठिन बनाता है, और अंततः इसे हल करने की तुलना में अधिक बग की ओर जाता है।

इसलिए मेरा मानना ​​है कि यदि डिफ़ॉल्ट तक नहीं पहुंचा जाना चाहिए - आपको इसे जोड़ना नहीं है।

ध्यान दें कि "नहीं पहुंचा जाना चाहिए" इसका मतलब है कि अगर यह सॉफ्टवेयर में बग तक पहुंच गया है - आपको उन मूल्यों का परीक्षण करने की आवश्यकता है जिनमें उपयोगकर्ता इनपुट आदि के कारण अवांछित मान हो सकते हैं।


3
अप्रत्याशित मामलों को प्राप्त करने का एक और सामान्य कारण: कोड के अन्य भागों को संशोधित किया जाता है, शायद वर्षों बाद।
हेंड्रिक ब्रम्मनमैन

वास्तव में, यह बहुत ही खतरनाक व्यवहार है। कम से कम, मैं एक जोर () खंड जोड़ूंगा। फिर जब भी बग होता है तो आसानी से पता चल जाता है।
कर्ट पेटीएन

5

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


5
"हर संभव मूल्य" को दुश्मनी से निपटने की संभावना नहीं है। यदि आप उस विशेष मान को स्पष्ट रूप से परिभाषित नहीं करते हैं, तो आप एक एनम को एक पूर्णांक में डाल सकते हैं। और कौन सा संकलक लापता मामले के बारे में चेतावनी देता है?
ट्रूविल

1
@TrueWill: हाँ, आप स्पष्ट कोडों का उपयोग कर सकते हैं जो मोटे तौर पर कोड लिखने के लिए समझ सकते हैं; समझने योग्य कोड लिखने के लिए, आपको उससे बचना चाहिए। gcc -Wall(सक्षम संकलक के सबसे कम आम भाजक की तरह) स्विच स्टेटमेंट में अनावरण किए गए एनम के बारे में चेतावनी देता है।
क्रिस डोड

4

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

switch(ResponseValue)
{
    default:
    case No:
        return false;
    case Yes;
        return true;
}

क्या defaultअभी भी यहाँ आवश्यक होने के बाद बृहदान्त्र है? या क्या ऐसा करने से कुछ विशेष वाक्यविन्यास की अनुमति मिलती है जो आपको इसे छोड़ देना चाहिए?
पोंकाडूडल

बृहदान्त्र की आवश्यकता है, यह एक टाइपो था, इसे मेरे ध्यान में लाने के लिए धन्यवाद।
डेग्यू

3

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

private static void switch1(String name) {
    switch (name) {
    case "Monday":
        System.out.println("Monday");
        break;
    case "Tuesday":
        System.out.println("Tuesday");
        break;
    }
}

लेकिन निम्नलिखित विधि में जो स्ट्रिंग को वापस करने की उम्मीद करता है, संकलन त्रुटियों से बचने के लिए डिफ़ॉल्ट केस काम आता है

    private static String switch2(String name) {
    switch (name) {
    case "Monday":
        System.out.println("Monday");
        return name;

    case "Tuesday":
        System.out.println("Tuesday");
        return name;

    default:
        return name;
    }
}

यद्यपि आप अंत में केवल वापसी विवरण होने के बिना डिफ़ॉल्ट मामले के बिना उपरोक्त विधि के लिए संकलन त्रुटि से बच सकते हैं, लेकिन डिफ़ॉल्ट केस प्रदान करना इसे अधिक पठनीय बनाता है।


3

कुछ (पुराने) दिशानिर्देश ऐसा कहते हैं, जैसे MISRA C :

अंतिम डिफ़ॉल्ट क्लॉज की आवश्यकता रक्षात्मक प्रोग्रामिंग है। यह खंड या तो उचित कार्रवाई करेगा या इसमें कोई उपयुक्त टिप्पणी होगी कि कोई कार्रवाई क्यों नहीं की गई।

यह सलाह पुरानी है क्योंकि यह वर्तमान में प्रासंगिक मानदंडों पर आधारित नहीं है। हरलन कासलर ने जो शानदार चूक की बात कही है:

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

जैसा कि हरलन ने भी दिखाया, स्विच के बाद एक डिफ़ॉल्ट केस के कार्यात्मक समकक्ष को फिर से बनाया जा सकता है। जो कि तुच्छ है जब प्रत्येक मामला प्रारंभिक प्रतिफल होता है।

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

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


2

आपके पास आने वाले गैर-अपेक्षित मूल्यों को पकड़ने के लिए एक डिफ़ॉल्ट होना चाहिए।

हालाँकि, मैं एड्रियन स्मिथ से असहमत हूं कि डिफ़ॉल्ट रूप से आपका त्रुटि संदेश पूरी तरह से अर्थहीन होना चाहिए। एक ऐसा संभाला मामला हो सकता है जिसे आपने forsee नहीं किया है (जो इस तरह का है) कि आपका उपयोगकर्ता देख कर समाप्त हो जाएगा और "अप्राप्य" जैसा संदेश पूरी तरह से व्यर्थ है और उस स्थिति में किसी की मदद नहीं करता है।

बिंदु में मामला, आप कितनी बार बीएसओडी से पूरी तरह से व्यर्थ हैं? या एक घातक अपवाद @ 0x352FBB3C32342?


उदाहरण - याद रखें कि यह केवल डेवलपर ही नहीं है जो हमेशा त्रुटि संदेश देखता है। हम वास्तविक दुनिया में रहते हैं, लोग गलतियाँ करते हैं।
जॉन हंट

2

यदि स्विच मान ( स्विच (चर )) डिफ़ॉल्ट मामले तक नहीं पहुंच सकता है, तो डिफ़ॉल्ट मामला बिल्कुल भी आवश्यक नहीं है। यहां तक ​​कि अगर हम डिफॉल्ट मामले को रखते हैं, तो यह बिल्कुल भी निष्पादित नहीं होता है। यह मृत कोड है।


2

यह एक वैकल्पिक कोडिंग 'कन्वेंशन' है। उपयोग के आधार पर इसकी आवश्यकता है या नहीं। मेरा व्यक्तिगत रूप से मानना ​​है कि अगर आपको इसकी आवश्यकता नहीं है तो यह नहीं होना चाहिए। कुछ ऐसा क्यों शामिल है जिसका उपयोग या उपयोग उपयोगकर्ता द्वारा नहीं किया जाएगा?

यदि केस की संभावनाएं सीमित हैं (यानी एक बूलियन) तो डिफ़ॉल्ट क्लॉज बेमानी है !


2

यदि किसी switchबयान में कोई डिफ़ॉल्ट मामला नहीं है , तो व्यवहार अप्रत्याशित हो सकता है यदि वह मामला किसी समय पर उठता है, जो विकास के स्तर पर अनुमानित नहीं था। किसी defaultमामले को शामिल करना एक अच्छा अभ्यास है ।

switch ( x ){
  case 0 : { - - - -}
  case 1 : { - - - -}
}

/* What happens if case 2 arises and there is a pointer
* initialization to be made in the cases . In such a case ,
* we can end up with a NULL dereference */

इस तरह की प्रथा का परिणाम बग के रूप में हो सकता है जैसे NULL dereference , मेमोरी लीक के साथ-साथ अन्य प्रकार के गंभीर कीड़े

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


2

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


1

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


1

मैं ऊपर वानवरिल के सबसे अधिक मतदान के जवाब से असहमत हूं।

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

  1. Nonexerateive स्विच स्टेटमेंट: जिनका हमेशा डिफ़ॉल्ट मान होना चाहिए । जैसा कि नाम से पता चलता है कि वे कथन हैं जो सभी संभावित मूल्यों को शामिल नहीं करते हैं। यह भी संभव नहीं हो सकता है, उदाहरण के लिए पूर्णांक मान या स्ट्रिंग पर एक स्विच स्टेटमेंट। यहाँ मैं वानवारिल के उदाहरण का उपयोग करना चाहूँगा (यह उल्लेख किया जाना चाहिए कि मुझे लगता है कि उन्होंने इस उदाहरण का उपयोग एक गलत सुझाव देने के लिए किया था। मैं इसका इस्तेमाल यहाँ विपरीत स्थिति बताने के लिए करता हूँ -> एक डिफ़ॉल्ट कथन का उपयोग करें):

    switch(keystroke)
    {
      case 'w':
        // move up
      case 'a':
        // move left
      case 's':
        // move down
      case 'd':
        // move right
      default:          
        // cover all other values of the non-exhaustive switch statement
    }
    

    खिलाड़ी किसी अन्य कुंजी को दबा सकता है। तब हम कुछ नहीं कर सकते थे (यह केवल डिफ़ॉल्ट केस में एक टिप्पणी जोड़कर कोड में दिखाया जा सकता है) या उदाहरण के लिए स्क्रीन पर कुछ प्रिंट करना चाहिए। यह मामला प्रासंगिक है क्योंकि ऐसा हो सकता है।

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

    public enum GradeSystemType {System1To6, SystemAToD, System0To100}
    

    फिर हमें इस एनम के एक वैरिएबल की जरूरत है GradeSystemType type = ...। एक संपूर्ण स्विच स्टेटमेंट इस तरह दिखेगा:

    switch(type)
    {
      case GradeSystemType.System1To6:
        // do something
      case GradeSystemType.SystemAToD:
        // do something
      case GradeSystemType.System0To100:
        // do something
    }
    

    इसलिए अगर हम विस्तार करते हैं GradeSystemType उदाहरण के System1To3लिए स्टैटिक कोड विश्लेषण टूल का यह पता लगाना चाहिए कि कोई डिफ़ॉल्ट क्लॉज नहीं है और स्विच स्टेटमेंट संपूर्ण नहीं है इसलिए हम सहेज रहे हैं।

बस एक अतिरिक्त बात। यदि हम हमेशा एक defaultक्लॉज का उपयोग करते हैं , तो ऐसा हो सकता है कि स्थैतिक कोड विश्लेषण उपकरण संपूर्ण या गैर-संपूर्ण स्विच स्टेटमेंट का पता लगाने में सक्षम नहीं है क्योंकि यह हमेशा defaultक्लॉज का पता लगाता है । यह सुपर खराब है क्योंकि हमें सूचित नहीं किया जाएगा यदि हम एनम को एक और मूल्य से बढ़ाते हैं और इसे एक स्विच स्टेटमेंट में जोड़ना भूल जाते हैं।


0

स्विच स्टेटमेंट में हमेशा एक डिफ़ॉल्ट क्लॉज होना चाहिए? डिफ़ॉल्ट केस के साथ कोई स्विच केस मौजूद नहीं हो सकता है, स्विच केस में डिफ़ॉल्ट केस switch(x)इस केस x में स्विच वैल्यू को ट्रिगर करेगा जब किसी अन्य केस वैल्यू के साथ मैच नहीं होगा।


0

मेरा मानना ​​है कि यह काफी विशिष्ट भाषा है और सी ++ केस के लिए एनम वर्ग के लिए एक मामूली बात है प्रकार के । जो पारंपरिक सी एनम की तुलना में अधिक सुरक्षित दिखाई देता है। परंतु

यदि आप std के कार्यान्वयन को देखते हैं :: इसकी बाइट को कुछ इस तरह देखें:

enum class byte : unsigned char {} ;

स्रोत: https://en.cppreference.com/w/cpp/language/enum

और इस पर भी विचार करें:

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

(C ++ 17 के बाद से)

स्रोत: https://en.cppreference.com/w/cpp/language/list_initialization

यह एनम वर्ग का एक उदाहरण है जो उन मूल्यों का प्रतिनिधित्व करता है जो एन्यूमरेटर परिभाषित नहीं हैं। इस कारण आप एनमों पर पूरा भरोसा नहीं कर सकते। आवेदन के आधार पर यह महत्वपूर्ण हो सकता है।

हालाँकि, मुझे वास्तव में यह पसंद है कि @Harlan Kassler ने अपने पोस्ट में क्या कहा और खुद कुछ स्थितियों में उस रणनीति का उपयोग करना शुरू कर देगा।

असुरक्षित एनम वर्ग का उदाहरण:

enum class Numbers : unsigned
{
    One = 1u,
    Two = 2u
};

int main()
{
    Numbers zero{ 0u };
    return 0;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.