स्विच स्टेटमेंट - डिफ़ॉल्ट केस को संभालना जब वह नहीं पहुंच सकता


16

अगर मैं एक एनम (जो मेरी कक्षा के स्वामित्व में है) से मूल्यों को संभालने के लिए एक स्विच स्टेटमेंट का उपयोग कर रहा हूं और मेरे पास प्रत्येक संभावित मूल्य के लिए एक मामला है - क्या यह "डिफ़ॉल्ट" केस को संभालने के लिए कोड जोड़ने के लायक है?

enum MyEnum
{
    MyFoo,
    MyBar,
    MyBat
}

MyEnum myEnum = GetMyEnum();
switch (myEnum)
{
    case MyFoo:
        DoFoo();
        break;
    case MyBar:
        DoBar();
        break;
    case MyBat:
        DoBat();
        break;
    default:
        Log("Unexpected value");
        throw new ArgumentException() 
}

मुझे नहीं लगता कि ऐसा इसलिए है क्योंकि यह कोड कभी भी (यूनिट परीक्षणों के साथ भी) नहीं पहुँचा जा सकता है। मेरा सहकर्मी असहमत है और सोचता है कि यह हमारे मायनम में जोड़े जा रहे नए मूल्यों के कारण अप्रत्याशित व्यवहार से बचाता है।

आप क्या कहते हैं, समुदाय?


मान लीजिए कि MyEnum एक गैर-अशक्त प्रकार है।
एसडी

3
"आज" यह गैर-अशक्त है। कल के बारे में क्या जब आप अब कोड को बनाए नहीं रख रहे हैं। या जब "MyBiz" को एनम में जोड़ा जाता है, लेकिन इस मामले के बारे में क्या? रखरखाव पर कालेब की टिप्पणी बहुत ही जर्मेन है।

1
अपने कंपाइलर को सिखाएं कि यदि सभी मामलों को कवर नहीं करना है तो यह एक घातक त्रुटि है।

क्या होगा यदि कोई अमान्य मान रखता है MyEnumतो उसे आपके स्विच से गुजरता है?
मावग का कहना है कि मोनिका

1
क्या भाषा? यदि जावा, आपको एनम के अंदर एक विधि डालनी चाहिए और केवल switchकथन (बहुरूपता) को पूरी तरह से समाप्त कर देना चाहिए ।
user949300

जवाबों:


35

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


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

Enumeration value 'MyBaz' not handled in switch

संकलक को उजागर किए गए मामलों का पता लगाने देना यह है कि यह काफी हद तक उस अगम्य defaultमामले की आवश्यकता को समाप्त करता है जिसने आपके प्रश्न को पहले स्थान पर प्रेरित किया।


2
ठीक है, आपने मुझे मना लिया है :) मुझे बस अपने कोड कवरेज नंबरों में सेंध को स्वीकार करना होगा।
एसडी

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

या, आप अपने ईनम प्रकार के लिए एक गैर-एनम मान डालें और इसका उपयोग करें।
मावग का कहना है कि मोनिका

5

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

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

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

MyEnum myEnum = (MyEnum) 3; // This could come from anywhere, maybe parsed from text?
// ... code goes on for a while

switch ( myEnum )
{
    case MyEnum.A:
        // ... handle A case
        break;
    case MyEnum.B:
        // ... handle B case
        break;
}

// ... code that expects either A or B to have happened

सरल जोड़कर case default:और एक अपवाद को फेंककर, आपने इस अजीब मामले के खिलाफ खुद को सुरक्षित किया है जहां "कुछ भी नहीं" होता है, लेकिन "कुछ" होना चाहिए था।

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


3

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


2

मैं कहता हूँ:

किसी अन्य प्रकार को जोड़ने का प्रयास करें MyEnum। फिर इस लाइन को बदलें:

MyEnum myEnum = GetMyEnum();

सेवा

MyEnum myEnum = SomethingElse;

फिर डिफ़ॉल्ट मामले के साथ और डिफ़ॉल्ट मामले के बिना अपना कोड चलाएं । आप कौन सा व्यवहार पसंद करते हैं?

डिफ़ॉल्ट केस होने से NULLमूल्यों को फंसाने और रोकने के लिए भी उपयोगी हो सकता है NullPointerExceptions


-1

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

यदि आपका कोड कभी भी परिवर्तित या संशोधित होने वाला नहीं है, और 100% बग फ्री है, तो डिफ़ॉल्ट केस को छोड़ना ठीक हो सकता है।

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


सभी -1 क्यों है?
मटनज़

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