2011-02-01 11 views
12

मेरे पास कोड का एक टुकड़ा निम्न जैसा है:एक विस्तार विधि बनाने के लिए सही कब है?

public class ActivityHelper 
{ 
    public void SetDate(IList<Activity> anActivityList) 
    { 
     foreach(Activity current in anActivityList) 
     { 
      current.Date = DateTime.Now; 
     } 
    } 
    //More methods, properties, fields, etc... 
} 

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

public static void SetDate(this IList<Activity> aList) 
{ 
    foreach(Activity current in anActivityList) 
    { 
     current.Date = DateTime.Now; 
    } 
} 

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

+1

ऐसा लगता है कि आप गलत सवाल पूछ रहे हैं। चाहे आप इसे एक विस्तार विधि बनाते हों या नहीं, काफी हद तक महत्वहीन नहीं है। लेकिन आपको लगभग निश्चित रूप से इसे ** स्थिर ** विधि बनाना चाहिए। कोई भी उदाहरण सदस्यों का उपयोग करने के बावजूद आपकी पहली विधि गैर स्थैतिक है; यह एक (मामूली) डिजाइन अशुद्ध-पैस है। – Timwi

+0

@ तिमवी हां, मैं बहुत अच्छी तरह से उस विधि को स्थिर बना सकता हूं और इस उदाहरण में मैंने ऐसा क्यों नहीं किया है इसका कोई विशिष्ट कारण नहीं है। किसी भी मामले में मुझे अभी भी लगता है कि यह एक अजीब विधि है। – brainimus

+0

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

उत्तर

12

ब्रैड एडम्स extension method design guidelines के बारे में लिखा है:,

  • एक अंतरफलक के हर कार्यान्वयन के लिए प्रासंगिक सहायक कार्यक्षमता प्रदान करने के लिए कहा है, तो कार्यक्षमता:

    निम्न परिदृश्यों में से किसी में विस्तार के तरीकों के उपयोग पर विचार कोर इंटरफ़ेस के संदर्भ में लिखा जा सकता है। ऐसा इसलिए है क्योंकि कंक्रीट कार्यान्वयन अन्यथा इंटरफेस को असाइन नहीं किया जा सकता है। उदाहरण के लिए, LINQ से ऑब्जेक्ट ऑपरेटरों को सभी IENumerable प्रकारों के लिए एक्सटेंशन विधियों के रूप में कार्यान्वित किया जाता है। इस प्रकार, किसी भी IENumerable <> कार्यान्वयन स्वचालित रूप से LINQ- सक्षम है।

  • जब एक उदाहरण विधि किसी प्रकार पर निर्भरता पेश करेगी, लेकिन ऐसी निर्भरता निर्भरता प्रबंधन नियमों को तोड़ देगी। उदाहरण के लिए, स्ट्रिंग से सिस्टम तक निर्भरता। यूरी शायद वांछनीय नहीं है, और इसलिए स्ट्रिंग.ToUri() इंस्टेंस विधि सिस्टम लौटा रही है। यूरी निर्भरता प्रबंधन परिप्रेक्ष्य से गलत डिजाइन होगा। एक स्थिर विस्तार विधि Uri.ToUri (यह स्ट्रिंग स्ट्र) सिस्टम लौट रहा है। यूरी एक बेहतर डिजाइन होगा।

6

मुझे लगता है कि विस्तार के तरीकों केवल उपयुक्त हैं अगर वहाँ एक सम्मोहक विधि एक विस्तार विधि बनाने के लिए कारण है।

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

व्यक्तिगत रूप से, यदि आपके एपीआई के उपयोगकर्ता की अपेक्षा पहले से ही "गतिविधिहेल्पर" वर्ग का उपयोग करना होगा, तो गतिविधियों के संग्रह के साथ काम करते समय, तो शायद मैं इसके लिए एक विस्तार विधि नहीं बनाउंगा। एक मानक, गैर-विस्तार विधि वास्तव में एक सरल एपीआई होगी, क्योंकि यह आसानी से समझा जा सकता है और खोजने योग्य है। विस्तार विधियां उपयोग दृष्टिकोण से मुश्किल होती हैं - आप एक ऐसी विधि को कॉल कर रहे हैं जो "जैसा दिखता है" यह वास्तव में मौजूद है, इसके अलावा कहीं और मौजूद है। हालांकि यह वाक्यविन्यास को सरल बना सकता है, यह रखरखाव और खोज क्षमता को कम करता है।

+2

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

+1

@ किर्क: हाँ, और यहां तक ​​कि जब आप जानते हैं कि यह कहीं मौजूद है, दस्तावेज ढूंढना आदि, तब तक मुश्किल हो सकता है जब तक आपको पता न हो कि यह कहां से आ रहा है ... –

0

वैसे मैं आमतौर पर उन कोडों को लिखने में मदद करने के लिए विस्तार विधियां बनाता हूं जिनमें चिकनी प्रवाह होता है। यह आम तौर पर आपके द्वारा बनाई जा रही विधि पर निर्भर करता है।

यदि आपको लगता है कि विधि पहले से ही ढांचे में होनी चाहिए और यह बहुत सामान्य है तो इसके लिए एक विस्तार विधि बनाना ठीक है।

लेकिन आपको पहले विश्लेषण करना होगा कि जिस वर्ग को आप विस्तारित कर रहे हैं वह हमेशा राज्य में होगा कि आपकी विस्तार विधि संभाल सकती है।

दिशानिर्देश के लिए ब्राड के अनुच्छेद

http://blogs.msdn.com/b/brada/archive/2009/01/12/framework-design-guidelines-extension-methods.aspx

4

करने के लिए यहाँ मेरे अनुभव विस्तार तरीकों में सबसे अच्छा काम है जब वे:

  • दुष्प्रभाव (विस्तार के तरीकों अपनी टीम के सबसे नहीं है लिखा है कि साइड इफेक्ट्स हैं, हमने हटा दिया है क्योंकि उन्होंने मदद की तुलना में अधिक समस्याएं पैदा की हैं)
  • प्रस्ताव कार्यक्षमता जो प्रत्येक संभावित उदाहरण या मूल्य पर लागू होती है टाइप वे विस्तार कर रहे हैं। (फिर से अपनी टीम से एक उदाहरण का हवाला देते हुए, string.NormalizeUrl() नहीं उचित नहीं है क्योंकि सभी स्ट्रिंग्स भी वैसे भी यूआरएल हो रहा है)
+0

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

+0

यह केंद्रीय प्रश्न के लिए वास्तव में उत्तरदायी नहीं है कि किसी को एक विस्तार विधि या "हेल्पर" कक्षा में नियमित विधि का उपयोग करना चाहिए या नहीं। –

+0

ओपी से पूछा गया दूसरा सवाल एक और सामान्य प्रकृति का है। मुझे कल्पना है कि रेक्स इसका जवाब दे रहा है, और मैं बस एक टिप्पणी कर रहा हूं। –

0

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

हालांकि, मैं आम तौर पर एक void returntype साथ एक्सटेंशन के तरीके की घोषणा से दूर चलाने की, जैसा कि मैंने इस धाराप्रवाह शैली वाक्य रचना है, जो आप बयान लिखने देता है की उपयोगिता लग रहा है, नकार दिया गया जब प्रश्न में विधि कुछ भी वापस नहीं करता है।

हालांकि, मुझे लगता है कि यह अपने तरीके IntelliSense द्वारा उठाया पाना उपयोगी हो सकता है ... :-)

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