2009-10-15 13 views
6

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

लेकिन मुझे नहीं पता कि घटनाक्रमों में प्रतिनिधियों का उपयोग कैसे किया जाता है।

क्या कोई साधारण उदाहरण (स्यूडोकोड या सी # या जावा में) बना सकता है जो घटनाओं से संबंधित प्रतिनिधि के कार्य को दिखाता है?

धन्यवाद!

उत्तर

8

(यह एक सी # नजरिए से सब है।)

मैं एक article about the differences between events and delegates है। इसमें नीचे वर्णित सब कुछ बहुत अधिक विस्तार से शामिल है।

मूल रूप से मुझे किसी संपत्ति की तरह एक घटना के बारे में सोचना पसंद है - यह एक विधि है, यह सब कुछ है। प्राप्त करने/सेट करने के बजाय, एक ईवेंट को जोड़/हटा दिया जाता है - जिसका अर्थ है "इस ईवेंट हैंडलर को जोड़ें" और "इस ईवेंट हैंडलर को हटाएं"। मूल में, यह सब एक घटना है।

सी # भी क्षेत्र-तरह की घटनाओं जो एक शॉर्टकट हैं:

public event EventHandler Foo; 

, दोनों एक क्षेत्र और एक घटना वाणी एक लगभग तुच्छ ऐड साथ/कार्यान्वयन को हटा दें। कक्षा के भीतर, Foo का जिक्र करते हुए क्षेत्र को संदर्भित किया जाता है। कक्षा के बाहर, Foo का जिक्र करते हुए घटना को संदर्भित किया जाता है।

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

myEventHandlers += value; 
इसी

आमतौर पर बिना निर्दिष्ट हैंडलर एक नया बहुस्त्र्पीय प्रतिनिधि बनाने शामिल सदस्यता खत्म:

myEventHandlers -= value; 

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

EventHandler handler = myEventHandlers; 
if (handler != null) 
{ 
    // You could pass in a different "sender" and "args" of course 
    handler(this, EventArgs.Empty); 
} 

घटनाओं का उपयोग करके, ग्राहकों को एक दूसरे के बारे में पता नहीं है, और घटना स्वयं (आमतौर पर) नहीं बढ़ा सकते हैं। दूसरे शब्दों में, यह encapsulation का एक पैटर्न है, जिसे भाषा और मंच दोनों के भीतर स्थिति दी गई है।

0

नेट कार्यक्रम केवल हुड के नीचे प्रतिनिधि हैं: वे कंपाइलर में कुछ वाक्य रचनात्मक चीनी प्रदान करते हैं।

आप एक प्रतिनिधि को सेट/रीसेट कर सकते हैं, लेकिन आप केवल ईवेंट हैंडलर को जोड़ या निकाल सकते हैं। तर्क यह है कि आप इस बात की परवाह नहीं करेंगे कि किसी और घटना के लिए कौन सा सदस्यता लेता है जबकि सादे प्रतिनिधियों को "कॉलबैक" परिदृश्य में अधिक उपयोग किया जाता है।

लेकिन सभी चीजों के अंत में वे बहुत समान हैं।

कुछ संसाधन:

C# events vs. delegates

Delegates & Events - A short Q&A

+1

नहीं, घटनाएं * प्रतिनिधि नहीं हैं। घटनाएं मूल रूप से विधियों को जोड़/हटाती हैं। यह कहकर कि प्रतिनिधि प्रतिनिधि हैं, कह रहे हैं कि गुण फ़ील्ड हैं। –

+0

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

2

आप की आवश्यकता होगी विशिष्ट के रूप में करने के लिए कौन-सी भाषा चाहते हैं। जहां तक ​​मुझे पता है, जावा में प्रतिनिधियों की अवधारणा नहीं है (हालांकि मैं पूरी तरह गलत हो सकता हूं); यह इवेंट हैंडलिंग के लिए एक पर्यवेक्षक पैटर्न का पालन करता है।

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

अगर मैं सी # में यह घोषणा करते हैं:

public event EventHandler MyEvent; 

और फोन इस तरह घटना:

MyEvent(this, EventArgs.Empty); 

यह वास्तव में सिर्फ एक पूर्ण घटना कार्यान्वयन के लिए कुछ आशुलिपि है:

private EventHandler myEventHandler; 

public event EventHandler MyEvent 
{ 
    add { myEventHandler += value; } 
    remove { myEventHandler -= value; } 
} 

और इसे बुला रहा है ...

और remove आयोजन का ईवेंट हैंडलर्स संलग्न करने के लिए उपभोक्ता कोड द्वारा उपयोग किया जाता है कि:
myEventHandler(this, EventArgs.Empty); 

यह सब कहना है कि एक वास्तविक event दो आपरेशन को उजागर करता है। डिफ़ॉल्ट (शॉर्टेंड) नोटेशन में, कंपाइलर प्रतिनिधि प्रकार का एक निजी उदाहरण सदस्य बनाता है और जिस तरह से मैंने ऊपर वर्णित किया है उसका उपयोग करता है। जब आप ईवेंट को "आह्वान" करते हैं, तो संकलक वास्तव में निजी बैकिंग प्रतिनिधि के नाम के लिए ईवेंट का नाम बदलता है। यही कारण है कि आप उप-वर्ग से event का आह्वान नहीं कर सकते हैं - यदि ईवेंट शॉर्टंड में बनाया गया है, तो बैकिंग सदस्य private है।

+0

जावा में प्रतिनिधि नहीं हैं, लेकिन आप एक इंटरफेस को कार्यान्वित करते हैं तो बस ईवेंट की सदस्यता लें: http://java.sun.com/docs/books/tutorial/uiswing/events/intro.html –

1

आप देख सकते हैं: http://msdn.microsoft.com/en-us/library/17sde2xt.aspx

उदाहरण यहां जारी रखा जाता है: http://msdn.microsoft.com/en-us/library/xwbwks95.aspx

मूल रूप से, के रूप में उल्लेख किया गया था, घटनाओं प्रतिनिधियों का सिर्फ विशेष मामलों रहे हैं, लेकिन .NET 3.5 आप में परिवर्तन के साथ प्रतिनिधियों का उपयोग किए बिना घटनाएं लिख सकते हैं, हालांकि हुड प्रतिनिधियों के तहत अभी भी लिखा गया है। http://msdn.microsoft.com/en-us/library/ms366768.aspx

2

अंतर सरल है:

आप इस लेख को देखें, तो वे किस तरह की घटनाओं के लिए लैम्ब्डा भाव और अनाम कार्यों का उपयोग करने के लिए दिखाई देते हैं।

delegate दो फ़ील्ड - ऑब्जेक्ट और MethodInfo के साथ एक कक्षा है।

eventdelegate का एक निजी क्षेत्र और दो सार्वजनिक विधियों add और remove है।

आमतौर पर घटना MulticastDelegate के हुड के तहत उपयोग किया जाता है - यह Delegate से वंचित वर्ग है और इसमें प्रतिनिधि की सूची शामिल है। यह घटना को कई ग्राहकों की अनुमति देता है।

+1

एक ईवेंट * उपयोग * कर सकते हैं एक निजी क्षेत्र है, लेकिन किसी संपत्ति से अधिक नहीं है। संकल्पनात्मक रूप से एक घटना सिर्फ जोड़/निकालना है। –

0

मैं जावा दुनिया में नया हूं लेकिन मुझे यह स्वीकार करना है कि मैं बहुत खुश हूं, लेकिन मुझे अभी भी कुछ सी # सामान याद आते हैं, इसलिए इस पैटर्न को डिजाइन करें जिसने मुझे अच्छे परिणाम दिए हैं, जावा विशेषज्ञों का उपयोग करने में कुछ कमी दिखाई देती है यह पैटर्न? यह केवल का समर्थन करता है जावा 8:

@FunctionalInterface 
public interface IEvent<TEventArgs extends Object> { 
    void invoke(TEventArgs eventArgs); 
} 

public class EventHandler<TEventArgs> 
{ 
    private ArrayList<IEvent<TEventArgs>> eventDelegateArray = new ArrayList<>(); 
    public void subscribe(IEvent<TEventArgs> methodReference) 
    { 
     eventDelegateArray.add(methodReference); 
    } 
    public void unSubscribe(IEvent<TEventArgs> methodReference) 
    { 
     eventDelegateArray.remove(methodReference); 
    } 
    public void invoke(TEventArgs eventArgs) 
    { 
     if (eventDelegateArray.size()>0) 
      eventDelegateArray.forEach(p -> p.invoke(eventArgs)); 
    } 
} 

public class DummyEventProducer 
{ 
    // The event 
    public EventHandler<String> myEvent = new EventHandler<>(); 

    public void onMyEvent(String A) 
    { 
     myEvent.invoke(A); 
    } 
} 


public class DummySubscriber { 

    // The method will be subscribed to the event 
    public void methodCallWhenEventGetTriggered(String eventArgs) 
    { 
     System.out.println("event fired with eventargs: " + eventArgs); 
    } 
} 


public class Main { 

    public static void main(String[] args) 
    { 
     // A dummy producer 
     DummyEventProducer producer = new DummyEventProducer(); 

     // A dummy subscribers 
     DummySubscriber testingInstanceA = new DummySubscriber(); 
     DummySubscriber testingInstanceB = new DummySubscriber(); 
     DummySubscriber testingInstanceC = new DummySubscriber(); 

     // We create decoupled event links because we want to un-subscribe later 
     IEvent<String> EventSink1 = testingInstanceA::methodCallWhenEventGetTriggered; 
     IEvent<String> EventSink2 = testingInstanceB::methodCallWhenEventGetTriggered; 
     IEvent<String> EventSink3 = testingInstanceC::methodCallWhenEventGetTriggered; 

     // subscribe to the event on dummy producer 
     producer.myEvent.subscribe(EventSink1); 
     producer.myEvent.subscribe(EventSink2); 
     producer.myEvent.subscribe(EventSink3); 

     // fire the event on producer 
     producer.onMyEvent("Hola MUNDO with decoupled subscriptions!"); 

     // unsubscribe to the event on dummy producer 
     producer.myEvent.unSubscribe(EventSink1); 
     producer.myEvent.unSubscribe(EventSink2); 
     producer.myEvent.unSubscribe(EventSink3); 

     // fire the event on producer again 
     producer.onMyEvent("Hola MUNDO! with no events subscriptions :("); 

     // IF YOU DON CARE ABOUT UNSUBSCRIBE YOU CAN LINK EVENTS DIRECTLY TO THE SUBSCRIBER 
     producer.myEvent.subscribe(testingInstanceA::methodCallWhenEventGetTriggered); 
     producer.myEvent.subscribe(testingInstanceB::methodCallWhenEventGetTriggered); 
     producer.myEvent.subscribe(testingInstanceC::methodCallWhenEventGetTriggered); 

     // fire the event on producer again 
     producer.onMyEvent("Hola MUNDO! with strong link subscriptions (cannot be un-subscribed"); 
    } 
} 

पूछने के लिए स्वतंत्र महसूस, सुधार, सुझाव =) सादर!

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