2009-07-06 12 views
7

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

मुझे पहले से ही एक मिला है और यह बहुत लक्षित है।

using System; 

namespace HelloNamespace { 

    class Greetings{ 
    public static void DisplayEnglish() { 
      Console.WriteLine("Hello, world!"); 
    } 
    public static void DisplayItalian() { 
      Console.WriteLine("Ciao, mondo!"); 
    } 
    public static void DisplaySpanish() { 
      Console.WriteLine("Hola, imundo!"); 
     } 
    } 

    delegate void delGreeting(); 

    class HelloWorld { 
     static void Main(string [] args) { 

    int iChoice=int.Parse(args[0]); 
    delGreeting [] arrayofGreetings={ 
      new delGreeting(Greetings.DisplayEnglish), 
      new delGreeting(Greetings.DisplayItalian), 
      new delGreeting(Greetings.DisplaySpanish)}; 

    arrayofGreetings[iChoice-1](); 
     } 
    } 
} 

लेकिन यह मुझे बिल्कुल नहीं बल्कि एक सशर्त से प्रतिनिधियों का उपयोग कर के लाभ प्रदर्शित नहीं करता है "अगर ... {}" का तर्क पार्स करके विधि चलाते हैं।

क्या किसी को पता है कि "अगर ... {}" के बजाय यहां प्रतिनिधि का उपयोग करना बेहतर क्यों है। क्या आपके पास अन्य उदाहरण भी हैं जो प्रतिनिधियों की उपयोगिता का प्रदर्शन करते हैं।

धन्यवाद!

+0

आह है, इस बात का डोनिस मार्शल के विज़ुअल सी # 2008 पहला उदाहरण है ...वास्तव में एक उचित पहले नमस्ते विश्व उदाहरण नहीं है, लेकिन फिर भी ... –

+0

नहीं, मैंने इसे एक ही लेखक के लिए "प्रोग्रामिंग माइक्रोसॉफ्ट विजुअल सी # 2005: द भाषा" पर पाया, अच्छा है कि उसने सी # 2008 के लिए एक नया संस्करण बनाया है, मेरे पास एक होगा इसे देखें –

+0

आपने अभी पेंडोरा के बॉक्स को खोला है :) – Gishu

उत्तर

5

सबसे आम वास्तविक दुनिया में हर रोज प्रतिनिधियों के उपयोग को परिभाषित करने के लिए एक प्रतिनिधि उन्हें गुजर जरूरत है कि मैं सी # में सोच सकता हूं कि घटना प्रबंधन होगा। जब आपके पास WinForm पर कोई बटन होता है, और जब आप बटन क्लिक करते हैं तो आप कुछ करना चाहते हैं, तो आप जो करते हैं, वह क्लिक करते समय बटन द्वारा कॉल करने के लिए एक प्रतिनिधि फ़ंक्शन को पंजीकृत करना समाप्त होता है।

यह सब आपके लिए विजुअल स्टूडियो द्वारा उत्पन्न कोड में दृश्यों के पीछे स्वचालित रूप से होता है, इसलिए आप यह नहीं देख सकते कि यह कहां होता है।

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

+1

असली दुनिया के उदाहरण के रूप में; मेरे पास एक कक्षा थी जिसने सीडी को फाइलें लिखीं, प्रतिनिधियों के बिना किसी उपयोगकर्ता को सूचित करने का एकमात्र तरीका प्रक्रिया को बाधित करना होता, हालांकि प्रतिनिधियों के साथ मैं एक ऐसी घटना को बढ़ाने में सक्षम था जिसने कॉलिंग प्रोग्राम को बिना किसी जोड़ के नोटिफिकेशन को संभालने की अनुमति दी मेरी सीडी लेखन कक्षा में सभी प्रकार की निर्भरताएं। – Mauro

+0

आप अपनी कक्षा के अंदर से ईवेंट कॉल करते समय सावधान रहना चाहेंगे, क्योंकि उन्हें एक ही थ्रेड पर निष्पादित किया जाता है, और आप अपनी कक्षा को ऐसा करने से रोक सकते हैं जो आप करना चाहते हैं! मुझे नहीं पता कि सीडी जलने अभी भी एक समय-संवेदी ऑपरेशन है, लेकिन यदि आप हैं तो आप अपने कार्यक्रमों को अपने स्वतंत्र धागे पर आग लगाने पर विचार करना चाहेंगे। – scwagner

5

प्रतिनिधियों एक विधि में कार्यक्षमता इंजेक्शन करने का एक शानदार तरीका है। कोड पुन: उपयोग के कारण वे बहुत मदद करते हैं।

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

उदाहरण के लिए LINQ द्वारा उपयोग की जाने वाली सभी IENumerable एक्सटेंशन विधियों को लें। वे सब के सब आम कार्यक्षमता को परिभाषित लेकिन कैसे वापसी डेटा का अनुमान है, या कैसे डेटा फ़िल्टर किया जाता है, हल कर, आदि ...

4

लैम्ब्डा भाव
प्रतिनिधियों ज्यादातर घटनाओं के साथ संयोजन के रूप में इस्तेमाल किया गया। लेकिन गतिशील भाषाओं ने उनके व्यापक उपयोग को दिखाया। यही वजह है कि जब हमें Lambda expressions मिल गया तो प्रतिनिधियों को सी # 3.0 तक कम किया गया। लैम्ब्डा अभिव्यक्तियों का उपयोग करके कुछ करना बहुत आसान है (जो एक प्रतिनिधि विधि उत्पन्न करता है)

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

1

प्रतिनिधियों का उपयोग अन्य वर्गों में कोड "कॉल" करने के लिए किया जाता है (जो आवश्यक रूप से समान, कक्षा, या .cs या यहां तक ​​कि एक ही असेंबली में नहीं हो सकता है)।

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

हालांकि, प्रतिनिधियों कार्यों कि "लाइव" कहीं जहां उदाहरण के लिए संगठनात्मक कारणों के लिए आप के लिए (आसानी से) पहुँच नहीं है कोड में करने के लिए संकेत दिए गए हैं।

0

एक अन्य प्रयोग है कि मैं एक महान वरदान लगता है कि अगर मैं एक ही कार्रवाई करने के लिए, एक ही डेटा पास या एक ही ऑब्जेक्ट प्रकार के कई उदाहरण में एक ही कार्रवाई को गति प्रदान करना चाहते हैं।

3

मैं कुछ उदाहरण है कि एक साधारण अगर-बाकी परिदृश्य से बाहर हैं सूची करने की कोशिश करेंगे:

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

  2. रणनीति डिजाइन पैटर्न को लागू करने। प्रतिनिधि को आवश्यक एल्गोरिदम/रणनीति कार्यान्वयन के लिए असाइन करें।

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

  4. घटना सदस्यता।

2

आपके उदाहरण में आपका बढ़िया वही है, इसलिए आपको वास्तव में स्ट्रिंग की सरणी है।

आप कमान पैटर्न में प्रतिनिधियों के उपयोग हासिल करने के लिए पसंद करते हैं, कल्पना आप:

public static void ShakeHands() 
{ ... } 

public static void HowAreYou() 
{ ... } 

public static void FrenchKissing() 
{ ... } 

आप एक ही हस्ताक्षर के साथ एक विधि स्थानापन्न सकता है, लेकिन विभिन्न कार्यों। आपने रास्ता बहुत आसान उदाहरण चुना है, मेरी सलाह होगी - जाओ और गहराई में एक पुस्तक सी # खोजें।

0

नेट में, प्रतिनिधियों भी जब एक पृष्ठभूमि धागे से यूआई अद्यतन करने की जरूरत है। आप धागा एक है कि नियंत्रण बनाया से अलग से नियंत्रण अद्यतन नहीं कर सकते रूप में, आप बनाने धागा के संदर्भ के भीतर (ज्यादातर this.Invoke का प्रयोग करके) अद्यतन कोड को लागू करने की जरूरत है।

1

प्रतिनिधियों और संबंधित वाक्यात्मक चीनी काफी सी # दुनिया (2.0+) को बदल दिया है प्रतिनिधियों प्रकार सुरक्षित समारोह संकेत दिए गए हैं - तो आप प्रतिनिधियों का उपयोग कहीं भी आप आह्वान/समय के भविष्य के बिंदु पर एक कोड ब्लॉक पर अमल करना चाहते हैं ।

ब्रॉड वर्गों मैं

कॉलबैक/घटना संचालकों के बारे में सोच सकते हैं: ऐसा करने जब EventX होता है। या जब आप मेरे async विधि कॉल के परिणामों के साथ तैयार हों तो ऐसा करें।

myButton.Click += delegate { Console.WriteLine("Robbery in progress. Call the cops!"); } 

LINQ: चयन, तत्वों, जहां आप इसे पाइपलाइन नीचे पार करने से पहले प्रत्येक तत्व के साथ कुछ करना चाहता हूँ के प्रक्षेपण आदि। जैसे उन सभी संख्याओं का चयन करें जो भी हैं, फिर उन

var list = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 } 
       .Where(delegate(int x) { return ((x % 2) == 0); }) 
       .Select(delegate(int x) { return x * x; });  
// results in 4, 16, 36, 64, 100 
2

यहां एक वास्तविक विश्व उदाहरण है। कुछ प्रकार के बाहरी कॉल को लपेटते समय मैं अक्सर प्रतिनिधियों का उपयोग करता हूं।उदाहरण के लिए, हमारे पास एक पुराना ऐप सर्वर है (जो मैं चाहता हूं कि अभी चलेगा) जिसे हम नेट रीमोटिंग से कनेक्ट करते हैं। मैं इस तरह एक 'safecall' समारोह से एक प्रतिनिधि में अनुप्रयोग सर्वर फोन करता हूँ:

private delegate T AppServerDelegate<T>(); 

private T processAppServerRequest<T>(AppServerDelegate<T> delegate_) { 
      try{ 
       return delegate_(); 
      } 
      catch{ 
       //Do a bunch of standard error handling here which will be 
       //the same for all appserver calls. 
      } 

     } 

//Wrapped public call to AppServer 
public int PostXYZRequest(string requestData1, string requestData2, 
    int pid, DateTime latestRequestTime){ 
      processAppServerRequest<int>(
       delegate { 
       return _appSvr.PostXYZRequest(
        requestData1, 
        requestData2, 
        pid, 
        latestRequestTime); 
       }); 

जाहिर त्रुटि हैंडलिंग थोड़ा की तुलना में बेहतर किया जाता है, लेकिन आप मोटा अनुमान लगा।

3

प्रतिनिधियों ने बस first class functions का कार्यान्वयन किया है और Higher Order Functions प्रदान करने के लिए भाषाओं का उपयोग करने की अनुमति दी है।

शैली की इस तरह के सिद्धांत लाभ यह है कि आम पहलुओं एक समारोह जो करता है बस यह करने के लिए (उदाहरण के एक डेटा संरचना traversing के लिए) की जरूरत है क्या में बाहर निकाला जा सकता है और एक और समारोह (या कार्यों) प्रदान की जाती है यह है कि है कुछ ऐसा करने के लिए कहा जाता है जैसे यह साथ जाता है।

कैननिकल कार्यात्मक उदाहरण map और fold हैं जिन्हें किसी अन्य ऑपरेशन के प्रावधान से सभी प्रकार की चीजों को बदलने के लिए बदला जा सकता है।

यदि आप टी की एक सूची जोड़ना चाहते हैं और कुछ फ़ंक्शन जोड़ना चाहते हैं जो दो टी लेता है और उन्हें एक साथ जोड़ता है (आंशिक अनुप्रयोग के माध्यम से) fold add 0 योग बन जाता है। fold multiply 1 उत्पाद बन जाएगा, fold max 0 अधिकतम। इन सभी उदाहरणों में प्रोग्रामर को इनपुट डेटा पर पुन: प्रयास करने के बारे में नहीं सोचना चाहिए, इनपुट की खाली होने पर क्या करना है इसके बारे में चिंता न करें।

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

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

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

सी-स्टाइल फ़ंक्शन पॉइंटर्स पर .NET प्रतिनिधि मॉडल का एक सिद्धांत लाभ यह है कि वे वास्तव में एक टुपल (डेटा के दो टुकड़े) कॉल करने के लिए फ़ंक्शन और वैकल्पिक ऑब्जेक्ट पर फ़ंक्शन कहलाते हैं। यह आप राज्य जो भी अधिक शक्तिशाली है के साथ काम करता है के बारे में पारित करने के लिए अनुमति देता है। चूंकि संकलक इसका उपयोग कर सकते अपनी पीठ (1) के पीछे कक्षाओं के निर्माण के लिए, इस वर्ग का एक नया उदाहरण का दृष्टांत और यह इस प्रकार closures की इजाजत दी में स्थानीय चर जगह।

(1) यह नहीं हमेशा यह करने के लिए करता है, लेकिन अब के लिए है कि एक कार्यान्वयन विस्तार

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