नई वस्तु को असाइन करते समय एक स्विच या एक शब्दकोश


12

हाल ही में, मैं बयानों के Dictionariesबजाय 1-1 रिश्तों का उपयोग करना पसंद कर रहा हूं Switch। मुझे यह लिखने में थोड़ा तेज़ लगता है और मानसिक रूप से प्रक्रिया में आसान होता है। दुर्भाग्य से, जब किसी वस्तु के नए उदाहरण के लिए मैपिंग होती है, तो मैं इसे इस तरह परिभाषित नहीं करना चाहता:

var fooDict = new Dictionary<int, IBigObject>()
{
    { 0, new Foo() }, // Creates an instance of Foo
    { 1, new Bar() }, // Creates an instance of Bar
    { 2, new Baz() }  // Creates an instance of Baz
}

var quux = fooDict[0]; // quux references Foo

उस निर्माण को देखते हुए, मैंने CPU चक्र और मेमोरी को 3 ऑब्जेक्ट्स को बर्बाद कर दिया है, जो कुछ भी उनके कंस्ट्रक्टरों में हो सकता है, कर रहा है और केवल उनमें से एक का उपयोग करके समाप्त हो गया है। मेरा यह भी मानना ​​है कि fooDict[0]इस मामले में अन्य वस्तुओं की मैपिंग करने से उन्हें एक ही बात का संदर्भ देने के लिए प्रेरित किया जाएगा, न कि एक नया उदाहरण बनाने के लिए Foo। इसके बजाय एक लंबोदर का उपयोग करने के लिए एक समाधान होगा:

var fooDict = new Dictionary<int, Func<IBigObject>>()
{
    { 0, () => new Foo() }, // Returns a new instance of Foo when invoked
    { 1, () => new Bar() }, // Ditto Bar
    { 2, () => new Baz() }  // Ditto Baz
}

var quux = fooDict[0](); // equivalent to saying 'var quux = new Foo();'

क्या यह उस बिंदु पर हो रहा है जहां यह बहुत भ्रामक है? यह याद रखना आसान है कि ()अंत में। या एक समारोह / अभिव्यक्ति के लिए मानचित्रण एक काफी सामान्य अभ्यास है? वैकल्पिक स्विच का उपयोग करना होगा:

IBigObject quux;
switch(someInt)
{
    case 0: quux = new Foo(); break;
    case 1: quux = new Bar(); break;
    case 2: quux = new Baz(); break;
}

कौन सा आह्वान अधिक स्वीकार्य है?

  • शब्दकोश, तेज लुकअप और कम कीवर्ड (केस और ब्रेक) के लिए
  • स्विच: कोड में आमतौर पर पाया जाता है, अप्रत्यक्ष के लिए एक फंक <> वस्तु के उपयोग की आवश्यकता नहीं होती है।

2
लैम्ब्डा के बिना आपको एक ही उदाहरण दिया जाएगा कि आप हर बार उसी कुंजी (जैसे fooDict[0] is fooDict[0]) के साथ लुकअप करते हैं । लैम्ब्डा और स्विच दोनों के साथ ऐसा नहीं है
शाफ़्ट फ्रीक

@ratchetfreak हाँ, मुझे वास्तव में इसका एहसास हुआ क्योंकि मैं उदाहरण लिख रहा था। मुझे लगता है कि मैंने इसे कहीं नोट किया है।
KChaloux

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

जवाबों:


7

यह फैक्ट्री पैटर्न पर एक दिलचस्प है । मुझे डिक्शनरी और लैम्ब्डा अभिव्यक्ति का संयोजन पसंद है; इसने मुझे एक नए तरीके से उस कंटेनर को देखा।

मैं सीपीयू चक्रों के बारे में आपके प्रश्न में चिंता को अनदेखा कर रहा हूं क्योंकि आपने टिप्पणियों में उल्लेख किया था कि गैर-लंबोदर दृष्टिकोण आपको प्रदान करने की आवश्यकता नहीं है।

मुझे लगता है कि एप्रोच (स्विच बनाम डिक्शनरी + लैम्ब्डा) ठीक होने वाला है। केवल सीमा यह है कि डिक्शनरी का उपयोग करके, आप लौटे वर्ग को उत्पन्न करने के लिए आपके द्वारा प्राप्त किए जा सकने वाले इनपुट के प्रकारों को सीमित कर रहे हैं।

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

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


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

1
@ केचलौक्स: बेशक, अगर आप सिर्फ फैक्ट्री मेथड पैटर्न का इस्तेमाल कर रहे हैं, तो आपका ऐसा case 0: quux = new Foo(); break;हो जाता है case 0: return new Foo();जो स्पष्ट रूप से लिखने में आसान है और पढ़ने में बहुत आसान है{ 0, () => new Foo() }
pdr

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

1
@ केचलौक्स: मैं स्वीकार करता हूं कि मैं हाल ही में किसी शब्दकोश के साथ स्विच / केस को बदलने के जुनून पर उत्सुक नहीं हूं। मैंने अभी तक ऐसा कोई मामला नहीं देखा है जहाँ अपनी पद्धति में स्विच को सरल और अलग करना अधिक प्रभावी नहीं था।
पीडीआर

@pdr जुनून यहां उपयोग करने के लिए एक मजबूत शब्द है। मूल्यों के बीच वन-ऑफ मैपिंग से निपटने के तरीके का निर्णय लेते समय अधिक विचार। मैं मानता हूं कि ऐसे मामलों में जहां इसे दोहराया जाता है, एक रचनात्मक विधि को अलग करने के लिए यह सबसे अच्छा है।
KChaloux

7

C # 4.0 आपको Lazy<T>क्लास देता है , जो आपके दूसरे समाधान के समान है, लेकिन "आलसी इनिशियलाइज़ेशन" को और अधिक स्पष्ट रूप से चिल्लाता है।

var fooDict = new Dictionary<int, Lazy<IBigObject>>()
{
    { 0, new Lazy(() => new Foo()) }, // Returns a new instance of Foo when invoked
    { 1, new Lazy(() => new Bar()) }, // Ditto Bar
    { 2, new Lazy(() => new Baz()) }  // Ditto Baz
}

ऊह, मुझे नहीं पता था कि।
KChaloux

वाह, बहुत अच्छा!
लॉरेंट बोर्गुल्ट-रॉय 16

2
हालांकि, एक बार Lazy.Value को लागू करने के बाद, यह अपने जीवनकाल के लिए उसी उदाहरण का उपयोग करता है। लाज़ी इनिशियलाइज़ेशन
Dan Lyons

बेशक, अन्यथा यह आलसी आरंभीकरण नहीं होगा, बस हर बार फिर से आरंभीकरण।
अवनेर शाहर-कश्तन

ओपी कहता है कि उसे हर बार नए उदाहरण बनाने की जरूरत है। लैम्ब्डा के साथ दूसरा समाधान और एक स्विच के साथ तीसरा समाधान दोनों करते हैं, जबकि पहला समाधान और आलसी <टी> कार्यान्वयन नहीं है।
दान ल्यों

2

स्थिर रूप से मुझे लगता है कि उनके बीच पठनीयता बराबर है। यह निर्भरता इंजेक्शन के साथ करना आसान है Dictionary

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

मैं switchस्टेटिक कोड पाथ के लिए स्टेटमेंट पसंद करूंगा , और Dictionaryडायनामिक कोड पाथ के लिए (जहां आप एंट्रीज को जोड़ या हटा सकते हैं)। कंपाइलर कुछ स्थिर अनुकूलन करने में सक्षम हो सकता है जिसके साथ switchयह नहीं हो सकता है Dictionary

दिलचस्प बात यह Dictionaryहै कि यह पैटर्न कभी-कभी लोग पायथन में करते हैं, क्योंकि पायथन में switchकथन का अभाव है । अन्यथा वे अगर-और जंजीरों का उपयोग करते हैं।


1

सामान्य तौर पर, मैं न तो पसंद करूंगा।

जो कुछ भी यह उपभोग कर रहा है उसे ए के साथ काम करना चाहिए Func<int, IBigObject>। फिर आपकी मैपिंग का स्रोत एक शब्दकोश या एक विधि हो सकती है जिसमें एक स्विच स्टेटमेंट या एक वेब सेवा कॉल या कुछ फ़ाइल लुकअप हो ... जो भी हो।

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

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