2012-12-28 5 views
9

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

उदाहरण के लिए, मान लीजिए कि मैं एक StackExchange वर्ग डालते हैं। इसमें PostQuestion और Search और AnswerQuestion जैसी विधियां होंगी।

अब, क्या हुआ अगर मैं मैन्युअल रूप से मेरी प्रतिष्ठा की गणना करने के लिए सुनिश्चित करें कि StackOverflow मुझे धोखा दे नहीं है चाहता था। मैं की तर्ज पर कुछ को लागू होता है: मैं StackExchange वर्ग के लिए एक विधि जोड़ सकते हैं

int rep=0; 
foreach(var post in StackExchangeInstance.MyPosts) 
{ 
    rep+=post.RepEarned; 
} 

है, लेकिन यह किसी भी आंतरिक की आवश्यकता नहीं है, और यह केवल इस कार्यक्रम के एक या दो अन्य भागों से प्रयोग किया जाता है ।

अब कल्पना करें कि इसके बजाय आपके पास इन विशिष्ट सहायक तरीकों में से 10 या 20 थे। निश्चित रूप से एक निश्चित परिदृश्य में उपयोगी, लेकिन निश्चित रूप से सामान्य मामले के लिए नहीं। मेरे विचार की तरह

namespace Mynamespace.Extensions.RepCalculations 
{ 
    public static RepCalcExtensions 
    { 
    public static int CalcRep(this Stackexchange inst){...} 
    } 
} 

नोट नाम स्थान

public static RepCalcHelpers 
{ 
    public static int CalcRep(StackExchange inst){ ... } 
} 

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

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

इस "पैटर्न" के साथ क्या कमियां हैं? क्या मैं इसके बजाय विरासत या संरचना, या सिर्फ एक अच्छा ओल 'स्थिर सहायक वर्ग के लिए चिपकना चाहिए?

+0

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

+0

बस स्पष्ट करने के लिए, आप ऐसा करेंगे ताकि आप किनारे-केस एक्सटेंशन विधियों वाले विशिष्ट 'उपयोग' कथनों सहित कुछ फ़ंक्शंस छुपा सकें ?? बहुत ही रोचक! –

+0

आप [यह] (http://stackoverflow.com/a/551600/649524) लिंक देख सकते हैं जो विस्तार विधियों के पेशेवर/विपक्ष को निर्दिष्ट करता है – Tilak

उत्तर

4

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

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

+0

खैर, स्थिरता मुझे लगता है कि उन्हें खोजने योग्य रखने के लिए आपका मित्र है। एक सामान्य '। एक्सटेंशन। *' नामस्थान मुझे लगता है कि यह काफी आसान रखेगा – Earlz

+0

@Earlz संगति निश्चित रूप से एक प्लस है। मैं कुछ भी उपयोगी करने के लिए कई 'उपयोग' कथन जोड़ने के खिलाफ वजन घटाना चाहता हूं। –

+0

ठीक है, आदर्श रूप से आप कभी भी कथन का उपयोग करके 2 से अधिक एक्सटेंशन जोड़ना नहीं चाहते हैं, इसलिए संतुलन को संतुलित करना मुश्किल होगा कि एक्सटेंशन को कितनी अच्छी तरह से समूहीकृत किया गया है – Earlz

0

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

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

0

आप तुलना कि विस्तार विधि एक सार्वजनिक उदाहरण विधि के बराबर है बनाने लगते हैं। यह वास्तव में नहीं है।

एक विस्तार विधि केवल एक सार्वजनिक स्थैतिक उपयोगिता विधि है जो कहने के लिए एक अधिक सुविधाजनक वाक्यविन्यास होता है।

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

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

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

+0

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

0

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

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

+0

में हैं, मुझे वास्तव में नहीं लगता कि अधिभार के लिए देर से माना जाने वाला एक सहायक उपयोगिता एक बुरी चीज है, ज्यादातर में मामलों। एक लिंक देखें, सुनिश्चित करें कि एक 'आईनेमरेबल काउंटर()' एक्सटेंशन विधि है, लेकिन कई चीजें जो आईन्यूमेरेबल को लागू करती हैं, पूरी सूची – Earlz

+0

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

+1

... और वास्तव में, वर्तमान में कार्यान्वित की गई गणना() LINQ विधि कुछ प्रकार की जांच करता है, और आईसीओलेक्शन में स्थगित कर देगा। अगर स्रोत एन्यूमेरिबल एक आईसीओलेक्शन है। भविष्यवाणी करने वाली विधि यह जांच नहीं करती है, हालांकि, अतिरिक्त लिंक एक्सटेंशन के अंत में गणना() का कोई भी उपयोग एक आईनेमरेबल को पारित किया जाएगा जो आईसीओलेक्शन नहीं है। – KeithS

संबंधित मुद्दे

 संबंधित मुद्दे