2010-09-20 13 views
7

मैं समझता हूं कि प्रतिनिधियों ने विधि कॉल को समाहित किया है। हालांकि मुझे उनकी ज़रूरत को समझने में कठिनाई हो रही है। प्रतिनिधि का उपयोग क्यों करें, वे किस स्थितियों के लिए डिजाइन किए गए हैं?प्रतिनिधियों के साथ क्या सौदा है?

+7

हर बार जब मैं इस प्रश्न का शीर्षक पढ़ता हूं तो मैं इसे जेरी सेनफेल्ड की आवाज़ में सुनता हूं। – Jess

उत्तर

11

एक प्रतिनिधि मूल रूप से एक विधि सूचक है। एक प्रतिनिधि हमें एक संदर्भ चर बनाने देता है, लेकिन कक्षा के उदाहरण के संदर्भ में, यह कक्षा के अंदर एक विधि को संदर्भित करता है। यह किसी भी विधि को संदर्भित करता है जिसमें रिटर्न प्रकार होता है और उस प्रतिनिधि द्वारा निर्दिष्ट पैरामीटर के समान पैरामीटर होते हैं। यह घटना का एक बहुत ही उपयोगी पहलू है। पूरी तरह से पढ़ने के लिए मैं आपको Head First C# (एंड्रयू स्टालमैन और जेनिफर ग्रीन द्वारा) विषय को पढ़ने का सुझाव दूंगा। यह प्रतिनिधि विषय के साथ-साथ .NET में सबसे अधिक अवधारणाओं को स्पष्ट रूप से समझाता है।

+0

भयानक वर्णन .. –

4

प्रतिनिधि Events के लिए अक्सर उपयोग किए जाते हैं। MSDN के अनुसार, .NET में प्रतिनिधियों निम्नलिखित के लिए तैयार कर रहे हैं:

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

MSDN से एक और अच्छी तरह डाल स्पष्टीकरण की methodimplementation के एक से अधिक कार्यान्वयन,

एक के बजाय एक एकल विधि इंटरफ़ेस का उपयोग कर के अच्छा उदाहरण आवश्यकता हो सकती है प्रतिनिधि IComparable या IComparable है। IComparable तुलना करने की विधि घोषित करता है, जो एक पूर्णांक को बराबर से कम, या रिश्ते से अधिक प्रकार के दो ऑब्जेक्ट्स के बीच निर्दिष्ट करता है। आईकॉम्पेरबल का उपयोग के आधार पर एक प्रकार के एल्गोरिदम के आधार पर किया जा सकता है, और प्रतिनिधि तुलना विधि का उपयोग करते हुए सॉर्ट एल्गोरिदम के आधार पर मान्य होगा, यह आदर्श नहीं है। क्योंकि तुलना करने की क्षमता कक्षा से संबंधित है, और तुलना एल्गोरिदम रन-टाइम पर नहीं बदलता है, एकल-विधि इंटरफ़ेस आदर्श.single-method इंटरफ़ेस आदर्श है।

.NET 2.0 के बाद से इसका उपयोग anonymous functions के लिए भी किया गया है।

विकिपीडिया प्रतिनिधिमंडल पैटर्न के बारे में एक अच्छा विवरण,

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

8

खैर, कुछ आम उपयोग:

  • घटना संचालकों - अतुल्यकालिक कॉल
  • से
  • कॉलबैक (यूआई कोड में बहुत आम "जब बटन क्लिक किया गया है, मैं इस कोड को निष्पादित करना चाहते हैं")
  • एक नया कार्य के साथ एक धागा (या ThreadPool)
  • निर्दिष्ट LINQ अनुमानों/स्थिति आदि
निष्पादित करने के लिए प्रदान करना

उनके बारे में सोचें कि विधि कॉल encapsulating के रूप में नहीं है। उनके बारे में सोचें कि किसी विशेष हस्ताक्षर के साथ व्यवहार/तर्क के कुछ मनमानी बिट को encapsulating। "विधि" भाग कुछ हद तक अप्रासंगिक है।

एक प्रतिनिधि प्रकार के बारे में सोचने का एक और तरीका एकल विधि इंटरफेस के रूप में है। इसका एक अच्छा उदाहरण IComparer<T> इंटरफ़ेस और इसके दोहरी, Comparison<T> प्रतिनिधि प्रकार है। वे एक ही मूल विचार का प्रतिनिधित्व करते हैं; कभी-कभी इसे एक प्रतिनिधि के रूप में व्यक्त करना आसान होता है, और दूसरी बार एक इंटरफ़ेस जीवन को आसान बनाता है। (आप निश्चित रूप से दोनों के बीच कनवर्ट करने के लिए कोड लिख सकते हैं।)

0

प्रतिनिधि आपको किसी विधि के संदर्भ को पारित करने की अनुमति देते हैं। एक सामान्य उदाहरण एक सॉर्ट फ़ंक्शन को तुलना विधि को पास करना है।

5

वे डिज़ाइन किए गए हैं, बहुत व्यापक रूप से बोलते हैं, क्योंकि जब आपके पास कोड होता है तो आपको अन्य कोड कॉल करने की आवश्यकता होगी - लेकिन आप संकलित समय पर नहीं जानते कि यह अन्य कोड क्या हो सकता है।

उदाहरण के तौर पर, विंडोज फॉर्म बटन के बारे में सोचें। ईवेंट पर क्लिक करें, जो एक प्रतिनिधि का उपयोग करता है। विंडोज फॉर्म प्रोग्रामर जानते हैं कि आप कुछ चाहते हैं कि उस बटन को दबाए जाने पर, लेकिन उनके पास यह जानने का कोई तरीका नहीं है कि आप क्या करना चाहते हैं ... यह कुछ भी हो सकता है!

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

0

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

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

"इलस्ट्रेटेड सी #" पुस्तक दान सोलिस से इस अवधारणा को सीखने के लिए सबसे आसान प्रवेश बिंदु है कि मैं भर में आ गए हैं प्रदान करता है:

http://www.amazon.com/Illustrated-2008-Windows-Net-Daniel-Solis/dp/1590599543

+0

जबकि मैं अप्रेस का बहुत शौकिया हूं ... "अभी तक प्रकाशित नहीं" पुस्तक को जोड़ने का क्या उपयोग है? – WernerCD

+0

@ वर्नर सीडी, हेड-अप के लिए धन्यवाद। दो पिछले संस्करण हैं इसलिए लिंक अपडेट कर रहा हूं :-) – IrishChieftain

+0

मुझे बिल्कुल सी # इलस्ट्रेटेड 2008 से प्यार है और 2010 के रिलीज होने के लिए इंतजार कर रहा है ... यह पहली बात थी जिसे मैंने देखा था :) – WernerCD

0

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

प्रतिनिधियों के पीछे कुछ उपयोगीता को समझने के लिए, भाषा सी और सी में कार्यों के प्रिंटफ "परिवार" पर विचार करें। मान लीजिए कि कोई "printf" का सामान्य उद्देश्य संस्करण चाहता है जो न केवल हो सकता है printf, fprintf, sprintf, आदि के रूप में उपयोग किया जाता है लेकिन एक आउटपुट को एक सीरियल पोर्ट, एक टेक्स्ट बॉक्स, एक टीसीपी पोर्ट, एक कुकी-फ्रॉस्टिंग मशीन, या जो कुछ भी बफर को प्रीलाकेट करने के बिना भेज सकता है। स्पष्ट रूप से इस तरह के एक समारोह को चरित्र-आउटपुट दिनचर्या के लिए एक फ़ंक्शन पॉइंटर स्वीकार करने की आवश्यकता होगी, लेकिन यह स्वयं ही अपर्याप्त होगा।

एक सामान्य कार्यान्वयन (दुर्भाग्य से मानकीकृत नहीं) एक सामान्य उद्देश्य gp_printf दिनचर्या होगा जो एक शून्य सूचक के प्रारूप (प्रारूप स्ट्रिंग और आउटपुट पैरामीटर के अलावा) स्वीकार करता है, और एक फ़ंक्शन के लिए एक सूचक जो एक वर्ण और शून्य को स्वीकार करता है सूचक। Gp_printf routine किसी भी उद्देश्य के लिए पास-इन शून्य पॉइंटर का उपयोग नहीं करेगा, लेकिन इसे चरित्र-आउटपुट फ़ंक्शन में पास कर देगा। उस फ़ंक्शन को पॉइंटर को FILE * पर डाला जा सकता है (यदि gp_printf को fprintf द्वारा बुलाया जा रहा है), या एक char ** (यदि इसे स्प्रिंटफ द्वारा बुलाया जा रहा है), या एक SERIAL_PORT * (यदि इसे serial_printf द्वारा बुलाया जा रहा है), या जो भी हो ।

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

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

1

ओवरस्सिम्प्लीफाइड: मैं कहूंगा कि एक प्रतिनिधि एक समारोह के लिए प्लेसहोल्डर है जब तक कि कुछ प्रतिनिधि को वास्तविक कार्य नहीं करता है। गैर-निर्दिष्ट प्रतिनिधियों को बुलाकर अपवाद फेंकता है।

भ्रम होता है क्योंकि परिभाषा, घोषणा, तत्कालता और प्रतिनिधियों के आविष्कार के बीच अक्सर थोड़ा अंतर होता है।

परिभाषा: के रूप में आप किसी भी वर्ग परिभाषा होगा
एक नाम स्थान में इस रखो।

public delegate bool DoSomething(string withThis); 

यह कक्षा-परिभाषा के समान है कि अब आप इस प्रतिनिधि के चर घोषित कर सकते हैं।

घोषणा:
इस रखो समारोह दिनचर्या में से एक की तरह आप किसी भी चर घोषित होता है।

DoSomething doSth; 

आरंभ होने और काम:
आमतौर पर आप इस एक साथ घोषणा के साथ करेंगे।

doSth = new DoSomething(MyDoSomethingFunc); 

"नया DoSomething (..)" तात्कालिकता है। DoSth = ... असाइनमेंट है।

ध्यान दें कि आपने पहले से ही "MyDoSomething" नामक एक फ़ंक्शन को परिभाषित किया होगा जो एक स्ट्रिंग लेता है और एक बूल देता है।

फिर आप फ़ंक्शन का आह्वान कर सकते हैं।

प्रार्थना:

bool result = doSth(myStringValue); 

घटनाक्रम:
आप देख सकते हैं जहां घटनाओं में आते हैं:

एक वर्ग के एक सदस्य के बाद से आमतौर पर एक घोषणा एक परिभाषा पर आधारित है।

class MyClass { 
    private int MyMember; 
} 

एक घटना की तरह एक घोषणा एक प्रतिनिधि पर आधारित है:

public delegate bool DoSomething(string withWhat); 

class MyClass { 
    private event DoSomething MyEvent; 
} 

पिछले उदाहरण के साथ अंतर यह है कि घटनाओं "विशेष" कर रहे हैं:

  1. आप कॉल कर सकते हैं एक अपवाद फेंकने के बिना un-assign घटनाओं।
  2. आप किसी ईवेंट को एकाधिक फ़ंक्शन असाइन कर सकते हैं। तब वे सभी को अनुक्रमिक रूप से बुलाया जाएगा। यदि उनमें से एक कॉल अपवाद फेंकता है, तो बाकी खेल नहीं पाएंगे।

वे वास्तव में प्रतिनिधियों के सरणी के लिए वाक्य रचनात्मक चीनी हैं।

मुद्दा यह है कि कुछ/कोई और आपके लिए असाइनमेंट करेगा।

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