2009-11-05 17 views
9

मैंने सोचा कि एक प्रतिनिधि उदाहरण एक समारोह उदाहरण के साथ अंतर-परिवर्तनीय था।प्रतिनिधि उदाहरण और विधि सूचक के बीच क्या अंतर है?

delegate int AddDelegate(int a, int b); 

AddDelegate DelegateInstance; 

public void DoStuff() 
{ 
    //I can call this without a delegate "instance": 
    MethodThatTakesAdd(Add); 

    //I can also call it WITH a delegate "instance" 
    DelegateInstance = Add; 
    MethodThatTakesAdd(DelegateInstance); 
} 

public int Add(int a, int b) 
{ 
    return a + b; 
} 

public void MethodThatTakesAdd(AddDelegate addFunction) 
{ 
    Console.WriteLine(addFunction(1, 2).ToString()); 
} 

यह बराबर होना दिखाई बुला दोनों तरीकों से आप केवल सी # उपयोग कर रहे हैं, और, आप अंतर कभी नहीं देखेंगे (कम से कम मैं अप करने के लिए नहीं है:

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

क्या वहां कोई है जो जानता है कि अंतर क्या है?

+1

आईएल कैसा दिखता है? क्या "हुड के तहत" कोई संकेत है कि उनका सामान्य रूप से अलग व्यवहार किया जाएगा? –

उत्तर

13

शब्दावली सुधार: विधि सूचक के बजाय, अधिक उपयुक्त शब्द विधि समूह है।

कार्यक्षमता के मामले में दो कथन समकक्ष हैं। यही है कि वे लगभग एक ही आईएल उत्पन्न करते हैं। अंतर यह है कि प्रतिनिधि मूल्य संग्रहित किया जाता है।

पहले मामले में आप विधि समूह को पास करते हैं विधिThatTakes में जोड़ें सीधे जोड़ें। इससे एक अस्थायी प्रतिनिधि मूल्य बनने का कारण बनता है और फिर MethodThatTakesAdd को पास कर दिया जाता है। यह प्रतिनिधि मूल्य कचरा संग्रह के अधीन है जब विधिThatTakes देता है रिटर्न जोड़ें क्योंकि यह मान संग्रहीत नहीं करता है।

दूसरे मामले में आपने प्रतिनिधि को बाहरी उदाहरण पर किसी क्षेत्र में सौंपा। यह आमतौर पर प्रतिनिधि के जीवनकाल को बढ़ाएगा और इसलिए आपके पिनवोक कॉल के दौरान एकत्रित कचरा का मौका कम कर देगा।

+0

यह बहुत सराहनीय लगता है, और जो मैं देख रहा हूं उसे समझाऊंगा! –

+0

http://msdn.microsoft.com/en-us/magazine/cc164193.aspx इसे "रिवर्स पी/इनवोक और डिलीगेट लाइफटाइम" अनुभाग में बताता है –

+0

@ जेरेडपार मुझे समझ में नहीं आता है।क्या यह 'AddDelegate DelegateInstance;' एक प्रतिनिधि ** उदाहरण ** है ?? यह सिर्फ 'AddDelegate' प्रकार का एक चर है। यह तार्किक लगता है कि एक प्रतिनिधि ** उदाहरण ** ** myDel + = नया MYDEL (myMethod); ** - या 'myDel + = myMethod;' (संक्षिप्त रूप में) का ** दायीं तरफ ** होगा। ।क्या मै गलत हु ? –

0

जबकि प्रतिनिधियों सी # या सी ++ में फ़ंक्शन पॉइंटर्स के रूप में सी # में समानार्थी कार्यक्षमता प्रदान करते हैं, वहां महत्वपूर्ण अंतर हैं। इनमें से महत्वपूर्ण यह है कि एक प्रतिनिधि एक श्रेणी है, सूचक नहीं।

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

4

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

public void DoStuff() 
{ 
    DelegateInstance += Add; 
    DelegateInstance += AnotherAdd; 
    DelegateInstance += YetAnotherAdd; 

    // Invoke Add(100, 200), AnotherAdd(100, 200), and YetAnotherAdd(100, 200) 
    DelegateInstance(100, 200); 
} 

अगर आप MSIL देखो MethodThatTakesAdd(Add) और MethodThatTakesAdd(DelegateInstance), की समतुल्यता के बारे में अपनी टिप्पणी के बारे में कि सी # संकलक लाइन MethodThatTakesAdd(Add) के लिए उत्पन्न करता है, तो आप देखेंगे कि संकलक एक प्रतिनिधि बनाने और Add() विधि लपेटकर है तुम्हारे लिए।

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