2009-10-15 24 views
6

Ho cercato di conoscere eventi/delegati, ma sono confuso circa il rapporto tra i due. So che i delegati ti permettono di invocare diverse funzioni senza bisogno di sapere quale particolare funzione viene invocata. (es .: una funzione grafica deve accettare input che sono diverse funzioni da rappresentare graficamente).Eventi/delegati in Java o C#

Ma non vedo come vengono utilizzati i delegati in Eventi.

Qualcuno può costruire un semplice esempio (in pseudocodice o C# o Java) che illustra il funzionamento dei delegati come correlato agli eventi?

Grazie!

risposta

8

(Questo è tutto da una prospettiva di C#.)

Ho un article about the differences between events and delegates. Questo copre tutto quanto menzionato di seguito in molti più dettagli.

Fondamentalmente mi piace pensare a un evento come se fosse una proprietà: è un paio di metodi, tutto qui. Invece di get/set, un evento ha add/remove - che significa "aggiungi questo gestore di eventi" e "rimuovi questo gestore di eventi". Al centro, è tutto un evento.

C# ha anche eventi sul campo come che sono una scorciatoia:

public event EventHandler Foo; 

dichiara sia un campo e un evento, con una quasi banale aggiunta/rimozione implementazione. All'interno della classe, facendo riferimento a Foo si fa riferimento al campo. Al di fuori della classe, facendo riferimento a Foo si riferisce all'evento.

L'idea di base è che un evento consenta ad altro codice di iscriversi e annullare l'iscrizione, trasferendo un delegato (l'evento gestore). Di solito, l'abbonamento viene implementato creando un nuovo delegato multicast contenente lo precedente elenco di gestori di eventi e il nuovo.Quindi, se siete memorizzare i gestori di eventi in un campo chiamato myEventHandlers, l'attuazione di sottoscrizione potrebbe essere:

myEventHandlers += value; 

Allo stesso modo disiscrizione di solito comporta la creazione di un nuovo delegato multicast senza il gestore specificato:

myEventHandlers -= value; 

Quindi, quando si desidera aumentare/attivare l'evento, è sufficiente chiamare il delegato multicast, di solito con un controllo di nullità per evitare che venga generata un'eccezione se nessuno si è iscritto:

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

Utilizzando gli eventi, gli abbonati non si conoscono e non possono sollevare l'evento da soli (in genere). In altre parole, è uno schema di incapsulamento, a cui è stato dato lo status sia nella lingua che nella piattaforma.

0

. Gli eventi Netto sono solo delegati sotto il cofano: forniscono del zucchero sintattico nel compilatore.

È possibile impostare/reimpostare un delegato, ma è possibile solo aggiungere o rimuovere un gestore eventi. La logica è che non ti importa di chi sottoscrive un evento mentre i delegati semplici sono più utilizzati in uno scenario di "callback".

Ma alla fine di tutto sono molto simili.

Alcune risorse:

C# events vs. delegates

Delegates & Events - A short Q&A

+1

No, gli eventi * non sono * delegati. Gli eventi sono metodi di aggiunta/rimozione, in pratica. Dire che gli eventi sono delegati è come dire che le proprietà sono campi. –

+0

Le proprietà IMHO DEVONO comportarsi come i campi, esattamente come gli eventi si comportano come delegati multicast. Altrimenti è fuorviante per l'utente di una classe poiché la proprietà e l'accesso al campo sono simili nell'origine così come l'invio di eventi e l'invio di delegati. Ciò non significa che una proprietà o un evento debba utilizzare l'implementazione predefinita (campo di supporto, supporto multicast). Significa semplicemente "proprietà/campo: ottieni/imposta un valore senza effetti collaterali" e "evento/delegato: esegui una richiamata". Con proprietà/eventi il ​​linguaggio ti dà un sacco di corda che puoi usare in modo ragionevole o impiccarti. – froh42

2

avrete bisogno per essere precisi su quale lingua desiderata. Per quanto ne so, Java non ha un concetto di delegati (anche se potrei sbagliarmi completamente); tende a seguire un modello di osservatore per la gestione degli eventi.

C#, tuttavia. Un event in C# ha la stessa relazione con un delegato come una proprietà ha il suo campo di supporto. Il delegato stesso è ciò che memorizza il puntatore alla funzione che gestisce l'evento (o, più precisamente, l'elenco di puntatori collegati all'evento, io uso il termine "puntatore" liberamente qui).

Se dichiaro questo in C#:

public event EventHandler MyEvent; 

e chiamare l'evento come questo:

MyEvent(this, EventArgs.Empty); 

E 'davvero solo un po' una scorciatoia per una piena attuazione evento:

private EventHandler myEventHandler; 

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

E chiamandolo ...

myEventHandler(this, EventArgs.Empty); 

Tutto questo per dire che un vero e proprio event espone due operazioni: add e remove che vengono utilizzati dal codice consumando per attaccare i loro gestori di eventi per l'evento. Nella notazione predefinita (stenografia), il compilatore crea un membro di istanza privato del tipo delegato e lo utilizza nel modo descritto sopra. Quando si "invoca" l'evento, il compilatore in realtà sostituisce il nome dell'evento per il nome del supporto privato delegato creato. Questo è il motivo per cui non è possibile richiamare un event da una sottoclasse: se l'evento viene creato in stenografia, il membro di supporto è private.

+0

Java non ha delegati, ma si implementa un'interfaccia quindi basta iscriversi all'evento: http://java.sun.com/docs/books/tutorial/uiswing/events/intro.html –

1

Potete guardare: http://msdn.microsoft.com/en-us/library/17sde2xt.aspx

L'esempio è continuato qui: http://msdn.microsoft.com/en-us/library/xwbwks95.aspx

In sostanza, come si è detto, gli eventi sono solo casi particolari di delegati, ma con i cambiamenti in .NET 3.5 si può scrivere eventi senza usare delegati, anche se sotto i cofani i delegati sono ancora scritti.

Se si guarda a questo articolo, mostrano come utilizzare le espressioni lambda e funzioni anonime per gli eventi: http://msdn.microsoft.com/en-us/library/ms366768.aspx

2

La differenza è semplice.

delegate è una classe con due campi - oggetto e MethodInfo.

event è un campo privato di tipo delegate e due metodi pubblici add e remove.

Viene solitamente utilizzato l'evento MulticastDelegate, è una classe ereditata da Delegate e contiene un elenco di delegati. Ciò consente all'evento di avere più abbonati.

+1

Un evento * può * utilizzare un campo privato, ma non ha più di una proprietà. Concettualmente un evento è solo l'add-on/remove. –

0

Sono nuovo al mondo Java ma devo ammettere che sono abbastanza felice, ma mi manca ancora qualche roba in C#, quindi progettare questo modello che mi ha dato buoni risultati, gli esperti di Java vedono qualche inconveniente nell'usare questo modello? Supporta solo java 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"); 
    } 
} 

Sentitevi liberi di chiedere, correzioni, suggerimenti =) i migliori saluti!