क्या प्रतिनिधि सिर्फ शॉर्टेंड इंटरफेस नहीं हैं?

मान लें कि हमारे पास है:

interface Foo 
{
 bool Func(int x);
}

class Bar: Foo
{
  bool Func(int x)
  {
   return (x>0);
  }  
}

class Baz: Foo
{
  bool Func(int x)
  {
   return (x<0);
  }  
}

अब हम बार और बाज़ को फूज़ के रूप में टॉस कर सकते हैं और अपने Func विधियों को कॉल कर सकते हैं।

प्रतिनिधि इसे थोड़ा सा सरल बनाते हैं:

delegate bool Foo(int x);

bool Bar(int x)
{
 return (x<0);
}

bool Baz(int x)
{
 return (x>0);
}

अब हम बार और बाज के आसपास फू प्रतिनिधियों के रूप में टॉस कर सकते हैं।

छोटे कोड प्राप्त करने के अलावा, प्रतिनिधियों का वास्तविक लाभ क्या है?

0

10 उत्तर

नहीं, प्रतिनिधि विधि पॉइंटर्स के लिए हैं। फिर आप यह सुनिश्चित कर सकते हैं कि संबंधित डब्ल्यू/प्रतिनिधि से जुड़े विधि का हस्ताक्षर सही है।

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

Take a look at the List<> class with the Find method. Now you get to define what determines if something is a match or not, without requiring items contained in the class to implement IListFindable or something similar.

0
जोड़ा

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

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

0
जोड़ा

जावा में बंद करने के लिए कम से कम एक प्रस्ताव (यानी अनाम प्रतिनिधि), वे एक सदस्य विधि के साथ इंटरफेस के बराबर हैं।

0
जोड़ा

कोई एक प्रतिनिधि के लिए एक इंटरफेस के रूप में प्रतिनिधियों के बारे में सोच सकता है जो परिभाषित करता है कि किस तर्क और वापसी प्रकार को एक विधि को प्रतिनिधि को फिट करना होगा

0
जोड़ा

एक प्रतिनिधि एक इंटरफ़ेस संदर्भ के साथ बहुत आम साझा करता है जिसमें कॉलर के दृष्टिकोण से एक ही विधि होती है।

पहले उदाहरण में, बाज और बार कक्षाएं हैं, जिन्हें विरासत में और तत्काल प्राप्त किया जा सकता है। दूसरे उदाहरण में, बाज़ और बार विधियां हैं।

इंटरफ़ेस अनुबंध से मेल खाने वाले किसी भी वर्ग में आप इंटरफ़ेस संदर्भ लागू नहीं कर सकते हैं। कक्षा को स्पष्ट रूप से घोषित करना होगा कि यह इंटरफ़ेस का समर्थन करता है। आप हस्ताक्षर से मेल खाने वाली किसी भी विधि के प्रतिनिधि प्रतिनिधि को लागू कर सकते हैं।

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

0
जोड़ा

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

0
जोड़ा

हां, एक प्रतिनिधि को एक विधि के साथ एक इंटरफेस के रूप में सोचा जा सकता है।

0
जोड़ा

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

छोटा, अधिक संक्षिप्त कोड भी एक योग्य लाभ है।

0
जोड़ा
यह सिर्फ सदस्य चर नहीं है। यह स्थानीय वैरिएबल या विधि के पैरामीटर भी है जो अज्ञात प्रतिनिधि को परिभाषित किया गया है।
जोड़ा लेखक Daniel Earwicker, स्रोत
@supercat सही। लेकिन आपको लगता है कि प्रतिनिधियों की तुलना में इंटरफेस "बेहतर काम" क्यों करेंगे? एक प्रतिनिधि तर्कसंगत रूप से एक ही विधि इंटरफ़ेस के समान होता है।
जोड़ा लेखक Daniel Earwicker, स्रोत
(1) "ढेर उदाहरण" सीएलआर में विशेष रूप से महंगा नहीं हैं। smellegantcode.wordpress देखें। कॉम/200 9/03/01/& hellip; (2) प्रतिनिधि शून्य MyDelegate (टी v) के साथ क्या गलत है, जहां टी: IFoo, IBar; ?
जोड़ा लेखक Daniel Earwicker, स्रोत
आह, तुम्हारा मतलब यह है? smellegantcode.wordpress .com/2010/04/17/& hellip;
जोड़ा लेखक Daniel Earwicker, स्रोत
@DanielEarwicker: एक रूटीन जिसमें एक बंद परिभाषित किया जाता है, स्थानीय चर को पकड़ने के लिए एक विशेष "छिपी हुई" कक्षा को परिभाषित करता है, किसी भी समय वे चर के दायरे में प्रवेश करते समय ऐसी कक्षा का एक उदाहरण बनाता है, और "सामान्य" स्थानीय के बजाय उस वर्ग के फ़ील्ड का उपयोग करता है चर। परिदृश्य जो बंद करने का उपयोग करते हैं वास्तव में प्रतिनिधियों के मुकाबले इंटरफेस के साथ बेहतर काम करेंगे।
जोड़ा लेखक supercat, स्रोत
@DanielEarwicker: कम से कम दो कारण: (1) मान लीजिए कि एक दिनचर्या कुछ स्थितियों में कार्रवाई को कॉल करेगी, और उस स्थिति में मैं इसे Foo (x) पर कॉल करना चाहता हूं। स्थानीय चर x के वर्तमान मूल्य के साथ। एक प्रतिनिधि के रूप में इस तरह के अनुरोध को पास करने के लिए दो ढेर उदाहरणों के निर्माण की आवश्यकता होती है: एक अस्थायी वर्ग वस्तु x , और इसे कॉल करने के लिए एक प्रतिनिधि को पकड़ने के लिए। एक इंटरफ़ेस प्रकार के रूप में अनुरोध को पास करने के लिए एक हीप इंस्टेंस (इंटरफ़ेस का कार्यान्वयन) बनाने की आवश्यकता होगी। इसे एक इंटरफेस-बाधित जेनेरिक के
जोड़ा लेखक supercat, स्रोत
(2) इंटरफेस में खुली जेनेरिक विधियां हो सकती हैं, जबकि प्रतिनिधि नहीं कर सकते हैं। मान लीजिए कि मेरे पास वस्तुओं का संग्रह कोई सामान्य आधार प्रकार नहीं है, लेकिन सभी IFoo और IBar को लागू करने के लिए बाध्य हैं। मैं एक बाहरी रूप से आपूर्ति की गई दिनचर्या चलाने में सक्षम होना चाहता हूं जो IFoo और IBar को बाध्य पैरामीटर लेता है। यह निर्दिष्ट करने का कोई तरीका नहीं है कि एक प्रतिनिधि टी: IFoo, IBar प्रकार का पैरामीटर लेता है लेकिन ऐसा करने वाला इंटरफ़ेस तरीका घोषित करना संभव है।
जोड़ा लेखक supercat, स्रोत
@DanielEarwicker: इसके साथ समस्या यह है कि प्रतिनिधि जो प्रतिनिधि बनाता है उसे टाइप टी निर्दिष्ट करना होगा। मान लीजिए कि किसी वर्ग में ऑब्जेक्ट्स का संग्रह होता है जो सभी I1 और I2 को लागू करते हैं, लेकिन उनके पास एक सामान्य आधार प्रकार नहीं है जो दोनों लागू करता है; यह एक ForAll विधि का पर्दाफाश करना चाहता है। यदि इस तरह की विधि ने इंटरफ़ेस IActUponConstrained {शून्य अधिनियम <�टी> (टी पैरा) कहां ऑब्जेक्ट स्वीकार किया है जहां टी: I1, I2;} , यह Act < टी> प्रत्येक आइटम पर उस इकाई के बिना जिसने
जोड़ा लेखक supercat, स्रोत
@DanielEarwicker: यदि कोई प्रतिबिंब का उपयोग नहीं करना चाहता है, तो सामान्य इंटरफ़ेस आवश्यक है क्योंकि जेनेरिक टाइपिंग पैरामीटर केवल कॉल स्टैक को "नीचे" (गहराई से) ले जा सकते हैं। अमूर्त वर्ग ThingImplementing का संग्रह व्युत्पन्न कक्षाओं के उदाहरण हो सकता है ThingImplementing .WithType जहां ActualType: I1, I2 । प्रत्येक उदाहरण जेनेरिक प्रकार से जुड़ा होता है जिसके साथ इसे बनाया गया था, लेकिन यदि अन्य प्रकार को उस प्रकार पैरामीटर का उपयोग करके बुलाया जा रहा है, तो उदाहरण को कॉल करना होगा। यदि Foo और बार
जोड़ा लेखक supercat, स्रोत
... दोनों इंटरफ़ेस, किसी प्रतिनिधि को परिभाषित करने का कोई तरीका नहीं है जिसमें I1 और I2 दोनों को बाध्य एक प्रकार पैरामीटर है, जिस पर ThingImplementing .WithType एक Foo पास कर सकता है, और जिस पर ThingImplementing .WithType एक बार पास कर सकता है । हालांकि, कोई भी IActUponConstrained के कार्यान्वयन को परिभाषित कर सकता है, इसे दोनों ऑब्जेक्ट्स में पास कर सकता है, और पहले कॉल Act (Foo param)
जोड़ा लेखक supercat, स्रोत
@DanielEarwicker: निश्चित रूप से। एक इंटरफ़ेस प्रकार की उपभोक्ता प्रकार की उपभोक्ता रखने की क्षमता जेनेरिक टाइप पैरामीटर की आपूर्ति करता है जो किनेट प्रतिनिधियों के साथ किया जा सकता है। असल में, मुझे यकीन नहीं है कि ढांचे में प्रतिनिधियों के लिए कोई वास्तविक आवश्यकता होगी यदि कंपेलर जेनेरिक इंटरफेस के लिए कुछ चीजें जो प्रतिनिधियों के लिए करते हैं (उदाहरण के लिए Invoke एक निश्चित हस्ताक्षर वाले विधि, एक वर्ग का निर्माण करें जिसका निर्माता उस इंटरफेस के दो कार्यान्वयन लेता है, और जो दोनों उदाहरणों को बुलाकर लागू करता है)। बेशक...
जोड़ा लेखक supercat, स्रोत
... जेनिक्स .NET 1.0 में मौजूद नहीं था, इसलिए अर्ध-जेनेरिक प्रतिनिधि एक आवश्यक स्टॉपगैप थे। संयोग से, मुझे आश्चर्य है कि क्यों प्रतिनिधि के कंपाइलर-जेनरेट किए गए डेरिवेटिव अपने स्वयं के प्रकार-विशिष्ट <�कोड> संयोजन और निकालें विधियों को परिभाषित नहीं करते हैं? ऐसी विधियां contravariant प्रतिनिधि प्रकारों के साथ ठीक से काम कर सकती हैं, जबकि Delegate.Combine नहीं कर सकता।
जोड़ा लेखक supercat, स्रोत
यह ध्यान रखना दिलचस्प है कि प्रतिनिधि सदस्यों तक पहुंच सकते हैं। उत्तीर्ण होने के लिए एक वर्ग लिपटे विधि आसानी से परिणामस्वरूप डेटा के लिए एक कूरियर के रूप में कार्य कर सकती है लेकिन प्रत्यक्ष पहुंच इसके बारे में जाने का एक तेज़ तरीका है।
जोड़ा लेखक Rick Minerich, स्रोत

एक सॉफ़्टवेयर इंजीनियरिंग परिप्रेक्ष्य से आप सही हैं, प्रतिनिधि फ़ंक्शन इंटरफेस की तरह हैं कि वे एक फ़ंक्शन इंटरफ़ेस को प्रोटोटाइप करते हैं।

इन्हें उसी तरह से भी इस्तेमाल किया जा सकता है: इसमें एक पूरी कक्षा को पारित करने के बजाय उस विधि में आपको केवल एक प्रतिनिधि में पास किया जा सकता है। यह एक बहुत सारे कोड बचाता है और अधिक पढ़ने योग्य कोड बनाता है।

इसके अलावा, लैम्ब्डा अभिव्यक्तियों के आगमन के साथ अब उन्हें आसानी से फ्लाई पर भी परिभाषित किया जा सकता है जो एक बड़ा बोनस है। हालांकि सी # में फ्लाई पर कक्षाएं बनाने के लिए यह संभव है, लेकिन यह वास्तव में बट में एक बड़ा दर्द है।

दोनों की तुलना एक दिलचस्प अवधारणा है। मैंने पहले नहीं सोचा था कि विचार एक केस केस और कोड स्ट्रक्चरिंग स्टैंडपॉइंट से कितने समान हैं।

0
जोड़ा

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

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

इस क्लासिक समस्या में कुछ अंतर्दृष्टि के लिए, और प्रतिनिधि क्यों वांछनीय हैं इसे पढ़ें और फिर यह

0
जोड़ा