कोड में स्विच को खत्म करने के तरीके [बंद]


175

कोड में स्विच के उपयोग को खत्म करने के तरीके क्या हैं?


18
जब आप उचित रूप से उपयोग किए जाते हैं, तो आप स्विच को क्यों समाप्त करना चाहेंगे? कृपया आप अपने सवाल पर विस्तार से बता सकते हैं।
आरबी।

मैं इस प्रश्न को सामुदायिक संपादन योग्य बनाता हूं क्योंकि हर कोई एक ही बात कह रहा है और सभी मतों को समेकित करना अच्छा हो सकता है।)
जोश

2
स्विच अन्य निर्देशों की तरह मानक नहीं है। उदाहरण के लिए, C ++ में, आप 'ब्रेक' को भूल सकते हैं और फिर आपके पास अप्रत्याशित परिणाम होंगे। इसके अलावा, यह 'ब्रेक' एक GOTO के समान है। मैंने कभी भी स्विच को खत्म करने की कोशिश नहीं की है, लेकिन यह सुनिश्चित करने के लिए कि वे मेरे पसंदीदा निर्देश नहीं हैं। ;)

2
मुझे लगता है कि वह स्विच कॉन्सेप्ट की बात कर रहा है न कि सी ++ या जावा स्विच स्टेटमेंट की। एक स्विच भी 'if-if if' ब्लॉक हो सकता है।
आउटलॉ प्रोग्रामर

2
आप चकित हो सकते हैं: फुर्तीले समुदाय में से एक बड़ी संख्या में उल्लेखनीय प्रोग्रामर हैं जो IF-IF अभियान में शामिल हैं: antiifcampaign.com/supporters.html
माइक ए

जवाबों:


267

स्विच-स्टेटमेंट प्रति सेवक नहीं हैं, लेकिन यदि आप ऑब्जेक्ट को कोडिंग उन्मुख कर रहे हैं, तो आपको विचार करना चाहिए कि क्या स्विच का उपयोग करने के बजाय एक स्विच का उपयोग बेहतर ढंग से बहुरूपता के साथ हल किया जाता है

बहुरूपता के साथ, यह:

foreach (var animal in zoo) {
    switch (typeof(animal)) {
        case "dog":
            echo animal.bark();
            break;

        case "cat":
            echo animal.meow();
            break;
    }
}

यह बन जाता है:

foreach (var animal in zoo) {
    echo animal.speak();
}

2
मैं में इसी तरह के सुझाव के कोसते किया जा रहा stackoverflow.com/questions/374239/... इतने सारे ppl बहुत अच्छा उदाहरण बहुरूपता में :) विश्वास नहीं है।
Nazgob

30
-1: मैंने कभी भी स्विच स्टेटमेंट का उपयोग नहीं किया है typeof, और यह उत्तर अन्य स्थितियों में स्विच स्टेटमेंट के आसपास काम करने के तरीकों या कारणों का सुझाव नहीं देता है।
केविन

3
मैं @ केविन से सहमत हूं - दिया गया उदाहरण वास्तव में यह नहीं दिखाता है कि बहुरूपता द्वारा स्विच को कैसे समाप्त किया जाए। सरल उदाहरण: यह मानों को स्विच करके enum का नाम प्राप्त करें, या किसी प्रकार के एल्गोरिथ्म में उपयुक्त मानों द्वारा कुछ कोड निष्पादित करें।
हॉटजार्ड

मैं सोच रहा था कि आप इसे कैसे खत्म कर सकते हैं इससे पहले कि आप किसी कारखाने में विशिष्ट कार्यान्वयन पर भरोसा कर सकें। और मुझे यहाँ एक बेहतरीन उदाहरण मिला है stackoverflow.com/a/3434505/711855
juanmf

1
बहुत ही मामूली उदाहरण।
गार्जियनएक्स

239

स्विच विवरण देखें :

आमतौर पर, पूरे प्रोग्राम में समान स्विच स्टेटमेंट बिखरे होते हैं। यदि आप एक स्विच में एक खंड जोड़ते या हटाते हैं, तो आपको अक्सर दूसरों को भी ढूंढना होगा और उनकी मरम्मत करनी होगी।

इसको हल करने के लिए रिफ्लेक्टिंग और रिफैक्टरिंग टू पैटर्न दोनों के दृष्टिकोण हैं।

यदि आपका (छद्म) कोड दिखता है:

class RequestHandler {

    public void handleRequest(int action) {
        switch(action) {
            case LOGIN:
                doLogin();
                break;
            case LOGOUT:
                doLogout();
                break;
            case QUERY:
               doQuery();
               break;
        }
    }
}

यह कोड उल्लंघन करता है ओपन क्लोज्ड सिद्धांत और हर नए प्रकार के एक्शन कोड के साथ नाजुक होता है। इसे मापने के लिए आप एक 'कमांड' ऑब्जेक्ट पेश कर सकते हैं:

interface Command {
    public void execute();
}

class LoginCommand implements Command {
    public void execute() {
        // do what doLogin() used to do
    }
}

class RequestHandler {
    private Map<Integer, Command> commandMap; // injected in, or obtained from a factory
    public void handleRequest(int action) {
        Command command = commandMap.get(action);
        command.execute();
    }
}

यदि आपका (छद्म) कोड दिखता है:

class House {
    private int state;

    public void enter() {
        switch (state) {
            case INSIDE:
                throw new Exception("Cannot enter. Already inside");
            case OUTSIDE:
                 state = INSIDE;
                 ...
                 break;
         }
    }
    public void exit() {
        switch (state) {
            case INSIDE:
                state = OUTSIDE;
                ...
                break;
            case OUTSIDE:
                throw new Exception("Cannot leave. Already outside");
        }
    }

तब आप एक 'स्टेट' ऑब्जेक्ट का परिचय दे सकते हैं।

// Throw exceptions unless the behavior is overriden by subclasses
abstract class HouseState {
    public HouseState enter() {
        throw new Exception("Cannot enter");
    }
    public HouseState leave() {
        throw new Exception("Cannot leave");
    }
}

class Inside extends HouseState {
    public HouseState leave() {
        return new Outside();
    }
}

class Outside extends HouseState {
    public HouseState enter() {
        return new Inside();
    }
}

class House {
    private HouseState state;
    public void enter() {
        this.state = this.state.enter();
    }
    public void leave() {
        this.state = this.state.leave();
    }
}

उम्मीद है की यह मदद करेगा।


7
कोड को कैसे रिफलेक्टर किया जाए, इसके महान उदाहरण के लिए धन्यवाद। हालाँकि मैं कह सकता हूँ कि भीख में इसे पढ़ना थोड़ा मुश्किल है (क्योंकि किसी को पूरी तरह से समझने के लिए कई फाइलों के बीच स्विच करना पड़ता है)
rshimoda

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

1
यह पूर्ण / अपूर्ण संचालन और निश्चित रूप से OOP में कोड को फिर से संरचित करने के बारे में एक बढ़िया उदाहरण है। अनेक अनेक धन्यवाद। मुझे लगता है कि यह उपयोगी होगा यदि ओओपी / डिज़ाइन पैटर्न के प्रस्तावक सुझाव देते हैं कि ओओपी अवधारणाओं को अवधारणाओं के बजाय ऑपरेटरों की तरह व्यवहार करना चाहिए । मेरा मतलब है कि "फैली हुई", "फैक्ट्री", "इम्प्लीमेंट्स", इत्यादि का उपयोग फाइलों, कक्षाओं, शाखाओं में इतनी बार किया जाता है। उन्हें ऑपरेटर के रूप में सरल होना चाहिए जैसे "+", "-", "+ =", "?:", "==", "->" आदि। जब कोई प्रोग्रामर उन्हें अपने दिमाग में बस ऑपरेटर के रूप में उपयोग करता है, तो फिर वह पूरी कक्षा के पुस्तकालय के बारे में सोच सकते हैं कार्यक्रम राज्य और (में) के पूर्ण संचालन के बारे में।
नेमस्पेसफॉर्म

13
मैं यह सोचना शुरू कर रहा हूं कि इसके मुकाबले SWITCH बहुत अधिक समझने योग्य और तार्किक है। और मुझे आमतौर पर ओओपी बहुत पसंद है, लेकिन यह संकल्प मेरे लिए बहुत सार है
जेके

1
कमांड ऑब्जेक्ट के साथ, कोड को Map<Integer, Command>एक स्विच की आवश्यकता नहीं होगी?
ataulm

41

एक स्विच एक पैटर्न है, चाहे स्विच स्टेटमेंट के साथ लागू किया गया हो, यदि चेन, लुकअप टेबल, ऊप बहुरूपता, पैटर्न मिलान या कुछ और।

क्या आप " स्विच स्टेटमेंट " या " स्विच पैटर्न " के उपयोग को खत्म करना चाहते हैं " ? पहले एक को समाप्त किया जा सकता है, दूसरा एक, केवल अगर एक और पैटर्न / एल्गोरिथ्म का उपयोग किया जा सकता है, और अधिकांश समय जो संभव नहीं है या ऐसा करने के लिए बेहतर दृष्टिकोण नहीं है।

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

और याद रखें कि संकलक बयान स्विच करने के लिए विभिन्न अनुकूलन कर सकते हैं। उदाहरण के लिए यदि आप संदेश प्रसंस्करण को कुशलतापूर्वक करना चाहते हैं, तो एक स्विच स्टेटमेंट बहुत ही बेहतर तरीका है। लेकिन दूसरी ओर एक स्विच स्टेटमेंट के आधार पर व्यवसाय के नियम चलाना संभवतः जाने का सबसे अच्छा तरीका नहीं है और आवेदन की खोज की जानी चाहिए।

यहां कथन स्विच करने के कुछ विकल्प दिए गए हैं:


1
क्या कोई अन्य बनाम वैकल्पिक विकल्पों का उपयोग करके संदेश प्रसंस्करण की तुलना कर सकता है?
माइक ए

37

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


यह मानते हुए, कि वह सी। में नहीं लिख रहा है :)
बर्नार्ड

1
C में, वह (ab?) फंक्शन
पॉइंट्स और स्ट्रक्चर्स का

आप किसी भी भाषा में FORT ^ H ^ H ^ H ^ H जावा लिख ​​सकते हैं। ; पी
बर्नार्ड

पूरी तरह से सहमत हैं - कोड लाइनों को कम करने के लिए स्विच बहुत अच्छा तरीका है, लेकिन इसके साथ भी मत खेलो।
हॉटजार्ड

21

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

आपका कोड कुछ इस तरह से दिखाई देगा:

void InitMap(){
    Map[key1] = Object/Action;
    Map[key2] = Object/Action;
}

Object/Action DoStuff(Object key){
    return Map[key];
}

4
भाषा पर निर्भर करता है। यह एक स्विच की तुलना में बहुत कम पठनीय हो सकता है
विंकियो व्रसालोविक

यह सही स्थिति में एक अच्छा ग्यारह समाधान है। मैंने यह मैपिंग कीकोड हाल ही में किया था, और यह उस उद्देश्य के लिए ठीक पढ़ा गया था।
बर्नार्ड

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

कुछ परिस्थितियों में क्लीनर हो सकता है। इसके अलावा धीमी, क्योंकि इसके लिए फ़ंक्शन कॉल की आवश्यकता होती है।
निक जॉनसन

1
जो आपकी चाबियों पर निर्भर करता है। एक कंपाइलर किसी भी फ़ंक्शन कॉल की आवश्यकता के बिना या तो किसी भी मामले में एक साधारण लुकअप या एक अत्यंत तेज़ स्थैतिक बाइनरी खोज में एक स्विच स्टेटमेंट संकलित कर सकता है।
निक जॉनसन

12

हर कोई बहुत बड़ा if elseब्लॉक प्यार करता है । पढ़ने में इतना आसान! मैं उत्सुक हूं कि आप स्विच स्टेटमेंट को क्यों हटाना चाहते हैं। यदि आपको एक स्विच स्टेटमेंट की आवश्यकता है, तो आपको शायद स्विच स्टेटमेंट की आवश्यकता है। गंभीरता से, मैं कहूंगा कि यह कोड के क्या करने पर निर्भर करता है। यदि सभी स्विच कर रहे हैं, तो फ़ंक्शन फ़ंक्शन (कहते हैं) आप फ़ंक्शन पॉइंटर्स पास कर सकते हैं। क्या यह एक बेहतर समाधान बहस का मुद्दा है।

भाषा यहां भी एक महत्वपूर्ण कारक है, मुझे लगता है।


13
मुझे लगता है कि व्यंग्य था :)
क्रेग दिवस

6

मुझे लगता है कि आप जो देख रहे हैं वह स्ट्रैटेजी पैटर्न है।

इसे कई तरीकों से लागू किया जा सकता है, जिनका उल्लेख इस प्रश्न के अन्य उत्तरों में किया गया है, जैसे:

  • मूल्यों का एक नक्शा -> कार्य करता है
  • बहुरूपता। (किसी ऑब्जेक्ट का उप-प्रकार यह तय करेगा कि यह किसी विशिष्ट प्रक्रिया को कैसे संभालता है)।
  • प्रथम श्रेणी के कार्य।

5

switch बयानों को बदलने के लिए अच्छा होगा यदि आप अपने आप को बयानों में नए राज्य या नया व्यवहार जोड़ते हैं:

इंट स्टेट;

स्ट्रिंग getString () {
   स्विच (राज्य) {
     स्थिति 0: // राज्य के लिए व्यवहार 0
           वापसी "शून्य";
     स्थिति 1: // राज्य 1 के लिए व्यवहार
           वापसी "एक";
   }
   नई IllegalStateException () फेंकें;
}

डबल getDouble () {

   स्विच (यह .स्टेट) {
     स्थिति 0: // राज्य के लिए व्यवहार 0
           वापसी 0d;
     स्थिति 1: // राज्य 1 के लिए व्यवहार
           वापसी 1d;
   }
   नई IllegalStateException () फेंकें;
}

नए व्यवहार को जोड़ने से कॉपी करने की आवश्यकता है switch, और एक अन्य को जोड़ने नए राज्यों साधन जोड़ने caseके लिए हर switch बयान।

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

पैटर्न मिलान , और कई if - elseब्लॉकों का उपयोग किया जा सकता है, हालांकि नए व्यवहार और नए राज्यों को जोड़ते समय वास्तव में समान समस्याएं हैं।

जो समाधान दूसरों ने "बहुरूपता" के रूप में सुझाया है वह राज्य पैटर्न का एक उदाहरण है :

प्रत्येक राज्य को अपनी कक्षा के साथ बदलें। कक्षा में प्रत्येक व्यवहार का अपना तरीका होता है:

IState राज्य;

स्ट्रिंग getString () {
   लौटने की स्थिति ।getString ();
}

डबल getDouble () {
   राज्य लौटना। डबलडॉग ();
}

हर बार जब आप एक नया राज्य जोड़ते हैं, तो आपको IStateइंटरफ़ेस का एक नया कार्यान्वयन जोड़ना होगा । एक switchदुनिया में, आप caseप्रत्येक में एक जोड़ रहे होंगे switch

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

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


4

यदि नहीं तो

मैं इस आधार का खंडन करता हूं कि स्विच स्वाभाविक रूप से खराब है।


3

खैर, एक के लिए, मुझे नहीं पता था कि स्विच का उपयोग एक विरोधी पैटर्न था।

दूसरी बात, स्विच को हमेशा स्टेटमेंट के साथ इफ / इफ बदले जा सकता है।


ठीक - अगर / elsifs के एक समूह के लिए स्विच सिंटैक्टिक मेथाडोन है।
माइक ए

3

तुम क्यों ऐसा चाहते हो? एक अच्छे कंपाइलर के हाथों में, एक स्विच स्टेटमेंट की तुलना में कहीं अधिक कुशल हो सकता है, जैसे कि / अन्य ब्लॉक (साथ ही पढ़ने में आसान हो), और केवल सबसे बड़े स्विचेस को किसी भी प्रकार से बदल दिए जाने की संभावना है अप्रत्यक्ष-लुकअप डेटा संरचना।


2
किस बिंदु पर आप संकलक के दूसरे अनुमान लगा रहे हैं, और संकलक के आधार पर अपने डिजाइन में बदलाव कर रहे हैं। डिज़ाइन को समस्या की प्रकृति का पालन करना चाहिए, न कि संकलक की प्रकृति का।
माइक ए

3

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

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

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


ठीक है, लेकिन हमें एक ही काम करने के 5 अलग-अलग, निरर्थक तरीकों की आवश्यकता क्यों है - सशर्त निष्पादन?
माइक ए

@ mike.amy: क्योंकि प्रत्येक विधि के अलग-अलग लाभ और लागत हैं और यह सब कम से कम लागत के साथ सबसे अधिक लाभ प्राप्त करने के बारे में है।
स्किज़

1

यदि स्विच विभिन्न प्रकार की वस्तुओं के बीच अंतर करने के लिए है, तो आप शायद उन वस्तुओं, या कुछ आभासी तरीकों का सटीक वर्णन करने के लिए कुछ कक्षाएं याद कर रहे हैं ...


1

C ++ के लिए

यदि आप आईएफ़ यानी एब्सट्रैक्ट फैक्ट्री की बात कर रहे हैं, तो मुझे लगता है कि आमतौर पर रजिस्टर करने के लिए बेहतर है कि एक रजिस्टरक्रॉफ्टरफुन्च (..) विधि हर "नए" स्टेटमेंट के लिए एक केस जोड़ने की आवश्यकता से बेहतर है। फिर सभी वर्गों को एक क्रिएटरफ़ंक्शन (..) बनाने और पंजीकृत करने की अनुमति देता है जिसे मैक्रो के साथ आसानी से लागू किया जा सकता है (यदि मैं उल्लेख करने की हिम्मत करता हूं)। मेरा मानना ​​है कि यह एक सामान्य दृष्टिकोण है जो कई ढांचे करते हैं। मैंने पहली बार इसे ET ++ में देखा था और मुझे लगता है कि कई चौखटे हैं जिनके लिए DECL की आवश्यकता होती है और IMPL मैक्रो इसका उपयोग करते हैं।


1

सी की तरह एक प्रक्रियात्मक भाषा में, फिर स्विच किसी भी विकल्प से बेहतर होगा।

एक वस्तु-उन्मुख भाषा में, फिर लगभग हमेशा अन्य विकल्प उपलब्ध होते हैं जो वस्तु संरचना, विशेष रूप से बहुरूपता का बेहतर उपयोग करते हैं।

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

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

जहां कोई स्पष्ट बहुरूपता नहीं चल रहा है, यह रणनीति पैटर्न को लागू करने के लायक हो सकता है ।

लेकिन अगर आपका विकल्प एक बड़ा IF ... THEN ... ELSE ब्लॉक है, तो इसे भूल जाइए।


1

ऐसी भाषा का उपयोग करें जो बिल्ट-इन स्विच स्टेटमेंट के साथ नहीं आती है। पर्ल 5 के मन में आता है।

गंभीरता से हालांकि, आप इससे बचना क्यों चाहेंगे? और अगर आपके पास इससे बचने का अच्छा कारण है, तो बस इसे टालना क्यों नहीं है?


1

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

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

यह एक महान विभाजन और जीत का उदाहरण है:

कहते हैं कि आपके पास किसी प्रकार का एक दुभाषिया है।

switch(*IP) {
    case OPCODE_ADD:
        ...
        break;
    case OPCODE_NOT_ZERO:
        ...
        break;
    case OPCODE_JUMP:
        ...
        break;
    default:
        fixme(*IP);
}

इसके बजाय, आप इसका उपयोग कर सकते हैं:

opcode_table[*IP](*IP, vm);

... // in somewhere else:
void opcode_add(byte_opcode op, Vm* vm) { ... };
void opcode_not_zero(byte_opcode op, Vm* vm) { ... };
void opcode_jump(byte_opcode op, Vm* vm) { ... };
void opcode_default(byte_opcode op, Vm* vm) { /* fixme */ };

OpcodeFuncPtr opcode_table[256] = {
    ...
    opcode_add,
    opcode_not_zero,
    opcode_jump,
    opcode_default,
    opcode_default,
    ... // etc.
};

ध्यान दें कि मुझे नहीं पता कि सी में opcode_table की अतिरेक को कैसे हटाया जाए। शायद मुझे इसके बारे में एक सवाल करना चाहिए। :)


0

सबसे स्पष्ट, भाषा स्वतंत्र, उत्तर 'अगर' की एक श्रृंखला का उपयोग करना है।

यदि आप जिस भाषा का उपयोग कर रहे हैं, उसमें फंक्शन पॉइंटर्स (C) हैं या फ़ंक्शंस हैं जो 1st क्लास वैल्यूज़ (Lua) हैं, तो आप ऐरे (या पॉइंटर्स टू) फंक्शन का उपयोग करके "स्विच" के समान परिणाम प्राप्त कर सकते हैं।

यदि आप बेहतर उत्तर चाहते हैं तो आपको भाषा पर अधिक विशिष्ट होना चाहिए।


0

स्विच स्टेटमेंट को अक्सर एक अच्छे OO डिज़ाइन द्वारा प्रतिस्थापित किया जा सकता है।

उदाहरण के लिए, आपके पास एक खाता वर्ग है, और खाते के प्रकार के आधार पर एक अलग गणना करने के लिए एक स्विच स्टेटमेंट का उपयोग कर रहे हैं।

मेरा सुझाव है कि इसे कई प्रकार के खाता वर्गों द्वारा प्रतिस्थापित किया जाना चाहिए, विभिन्न प्रकार के खाते का प्रतिनिधित्व करना चाहिए, और सभी को एक खाता इंटरफ़ेस लागू करना चाहिए।

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


0

निर्भर करता है कि आप इसे क्यों बदलना चाहते हैं!

कई व्याख्याकार ओपकोड निष्पादन के लिए स्विच स्टेटमेंट के बजाय 'कंप्यूटेड गोटो' का उपयोग करते हैं।

C / C ++ स्विच के बारे में मुझे जो याद आता है वह है पास्कल 'इन' और रेंज। मैं यह भी चाहता हूं कि मैं तार पर स्विच कर सकूं। लेकिन ये खाने के लिए एक कंपाइलर के लिए तुच्छ होते हैं, संरचनाओं और पुनरावृत्तियों और चीजों का उपयोग करते समय कड़ी मेहनत करते हैं। तो, इसके विपरीत, बहुत सारी चीजें हैं जो मैं चाहता हूं कि मैं एक स्विच के साथ बदल सकता हूं, अगर केवल सी का स्विच () अधिक लचीला था!


0

स्विच एक अच्छा तरीका नहीं है क्योंकि यह ओपन क्लोज प्रिंसिपल को तोड़ता है। यह मेरा इसे करने का तरीका है।

public class Animal
{
       public abstract void Speak();
}


public class Dog : Animal
{
   public virtual void Speak()
   {
       Console.WriteLine("Hao Hao");
   }
}

public class Cat : Animal
{
   public virtual void Speak()
   {
       Console.WriteLine("Meauuuu");
   }
}

और यहाँ इसका उपयोग कैसे करना है (अपना कोड लेना):

foreach (var animal in zoo) 
{
    echo animal.speak();
}

मूल रूप से हम जो कर रहे हैं वह माता-पिता को बच्चों के साथ क्या करना है, यह तय करने के बजाय बाल वर्ग को जिम्मेदारी सौंप रहा है।

तुम भी "Liskov प्रतिस्थापन सिद्धांत" पर पढ़ना चाहते हो सकता है।


0

साहचर्य सरणी का उपयोग करके जावास्क्रिप्ट में:
यह:

function getItemPricing(customer, item) {
    switch (customer.type) {
        // VIPs are awesome. Give them 50% off.
        case 'VIP':
            return item.price * item.quantity * 0.50;

            // Preferred customers are no VIPs, but they still get 25% off.
        case 'Preferred':
            return item.price * item.quantity * 0.75;

            // No discount for other customers.
        case 'Regular':
        case
        default:
            return item.price * item.quantity;
    }
}

यह बन जाता है:

function getItemPricing(customer, item) {
var pricing = {
    'VIP': function(item) {
        return item.price * item.quantity * 0.50;
    },
    'Preferred': function(item) {
        if (item.price <= 100.0)
            return item.price * item.quantity * 0.75;

        // Else
        return item.price * item.quantity;
    },
    'Regular': function(item) {
        return item.price * item.quantity;
    }
};

    if (pricing[customer.type])
        return pricing[customer.type](item);
    else
        return pricing.Regular(item);
}

के सौजन्य से


-12

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

वही वस्तु कारखानों के लिए जाता है।

यदि / अन्यथा ब्लॉक एक साधारण निर्माण है जो सभी को मिलता है। ऐसी कुछ चीजें हैं जो आप यह सुनिश्चित करने के लिए कर सकते हैं कि आपको कोई समस्या न हो।

सबसे पहले - एक बार से अधिक बार बयान देने की कोशिश न करें। यदि आप खुद को इंडेंट कर रहे हैं, तो आप इसे गलत कर रहे हैं।

 if a = 1 then 
     do something else 
     if a = 2 then 
         do something else
     else 
         if a = 3 then 
             do the last thing
         endif
     endif 
  endif

वास्तव में बुरा है - इसके बजाय ऐसा करो।

if a = 1 then 
   do something
endif 
if a = 2 then 
   do something else
endif 
if a = 3 then 
   do something more
endif 

अनुकूलन को धिक्कार है। इससे आपके कोड की गति पर बहुत फर्क नहीं पड़ता।

दूसरी बात, मैं एक आई ब्लॉक से बाहर निकलने से पीछे नहीं हटता, जब तक कि विशेष ब्रेक के माध्यम से बिखरे हुए पर्याप्त स्टेटमेंट न हों, इसे स्पष्ट करने के लिए

procedure processA(a:int)
    if a = 1 then 
       do something
       procedure_return
    endif 
    if a = 2 then 
       do something else
       procedure_return
    endif 
    if a = 3 then 
       do something more
       procedure_return
    endif 
end_procedure

संपादित करें : स्विच पर और मुझे क्यों लगता है कि यह मुश्किल है:

यहां एक स्विच स्टेटमेंट का उदाहरण दिया गया है ...

private void doLog(LogLevel logLevel, String msg) {
   String prefix;
   switch (logLevel) {
     case INFO:
       prefix = "INFO";
       break;
     case WARN:
       prefix = "WARN";
       break;
     case ERROR:
       prefix = "ERROR";
       break;
     default:
       throw new RuntimeException("Oops, forgot to add stuff on new enum constant");
   }
   System.out.println(String.format("%s: %s", prefix, msg));
 }

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

जैसे

for i from 1 to 1000 {statement1; statement2}
if something=false then {statement1; statement2}
while isOKtoLoop {statement1; statement2}

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

आशा है कि आपको अपने सवालों के जवाब मिल जायेंगे।


वाह - जाहिर है एक विवादास्पद जवाब। मुझे यह जानने में दिलचस्पी होगी कि मुझे क्या गलत मिला।
सीनबॉय

एर, बहुत जटिल होने के रूप में स्विच? मुझे नहीं पता ... मुझे लगता है कि आपके द्वारा उपयोग की जा सकने वाली कई भाषा सुविधाएँ नहीं होंगी। :) इसके अलावा, आपके केंद्रीय उदाहरण में, क्या ऐसा करना स्मार्ट नहीं होगा अगर (a == 1 || a == 2 || a == 3 कुछ करें?
लार्स वेस्टरग्रेन ने

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

4
"अनुकूलन को धिक्कार है। इससे आपके कोड की गति पर बहुत फर्क नहीं पड़ता है।" मेरा कोड मोबाइल प्लेटफ़ॉर्म पर चलता है। अनुकूलन मायने रखता है। इसके अलावा, स्विचेस कोड को सही ढंग से इस्तेमाल करने पर (साफ-सुथरा होने पर इसकी तुलना में if..elseif..elseif..elseif ...) कर सकते हैं। उन्हें कभी नहीं देखा? उन्हें जानें।
स्वाति

स्विच बिल्कुल जटिल नहीं है, लेकिन मैंने हमेशा समझ में घर्षण को कम करने के लिए कोड में उपयोग किए गए निर्माणों की संख्या को कम करने की कोशिश की है।
सीनबॉय
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.