Events/Delegates In Java or C#
Asked Answered
M

6

6

I've been trying to learn about events/delegates, but am confused about the relationship between the two. I know that delegates allow you to invoke different functions without needing to know what particular function is being invoked. (eg: a graphing function needs to accept inputs that are different functions to be graphed).

But I don't see how delegates are used in Events.

Can someone construct a simple example (in pseudocode or C# or Java) that illustrates the workings of Delegates as related to Events?

Thanks!

Maury answered 15/10, 2009 at 2:13 Comment(0)
F
8

(This is all from a C# perspective.)

I have an article about the differences between events and delegates. That covers everything mentioned below in a lot more detail.

Basically I like to think of an event as being like a property - it's a pair of methods, that's all. Instead of get/set, an event has add/remove - meaning "add this event handler" and "remove this event handler". At the core, that's all an event is.

C# also has field-like events which are a shortcut:

 public event EventHandler Foo;

declares both a field and an event, with a nearly trivial add/remove implementation. Within the class, referring to Foo refers to the field. Outside the class, referring to Foo refers to the event.

The basic idea is that an event allows other code to subscribe to and unsubscribe from it, by passing in a delegate (the event handler). Usually, subscription is implemented by creating a new multicast delegate containing the previous list of event handlers and the new one. So if you're storing the event handlers in a field called myEventHandlers, the subscription implementation might be:

myEventHandlers += value;

Similarly unsubscription usually involves creating a new multicast delegate without the specified handler:

myEventHandlers -= value;

Then when you want to raise/fire the event, you just call that multicast delegate - usually with a nullity check to avoid an exception being thrown if no-one has subscribed:

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

Using events, the subscribers don't know about each other, and can't raise the event themselves (usually). In other words, it's a pattern of encapsulation, which has been given status within both the language and the platform.

Felipa answered 15/10, 2009 at 5:34 Comment(0)
R
2

You'll need to be specific as to which language you want. As far as I know, Java doesn't have a concept of delegates (though I could be completely wrong); it tends to follow an observer pattern for event handling.

C#, however, does. An event in C# has the same relation to a delegate as a property has to its backing field. The delegate itself is what stores the pointer to the function that handles the event (or, more accurately, the list of pointers attached to the event; I use the term "pointer" loosely here).

If I declare this in C#:

public event EventHandler MyEvent;

And call the event like this:

MyEvent(this, EventArgs.Empty);

It's really just some shorthand for a full event implementation:

private EventHandler myEventHandler;

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

And calling it...

myEventHandler(this, EventArgs.Empty);

All this is to say that an actual event exposes two operations: add and remove that are used by the consuming code to attach their event handlers to the event. In the default (shorthand) notation, the compiler creates a private instance member of the delegate type and uses it in the way that I described above. When you "invoke" the event, the compiler actually substitutes the name of the event for the name of the private backing delegate it created. This is why you can't invoke an event from a subclass--if the event is created in shorthand, then the backing member is private.

Realism answered 15/10, 2009 at 2:21 Comment(1)
Java doesn't have delegates, but you implement an interface then just subscribe to the event: java.sun.com/docs/books/tutorial/uiswing/events/intro.htmlAsmodeus
A
1

You can look at: http://msdn.microsoft.com/en-us/library/17sde2xt.aspx

The example is continued here: http://msdn.microsoft.com/en-us/library/xwbwks95.aspx

Basically, as was mentioned, events are just special cases of delegates, but with the changes in .NET 3.5 you can write events without using delegates, though under the hood delegates are still written.

If you look at this article, they show how to use lambda expressions and anonymous functions for events: http://msdn.microsoft.com/en-us/library/ms366768.aspx

Asmodeus answered 15/10, 2009 at 2:24 Comment(0)
C
1

Difference is simple.

delegate is a class with two fields - object and MethodInfo.

event is a private field of type delegate and two public methods add and remove.

Usually under the hood of event MulticastDelegate is used - it's a class inherited from Delegate and containing list of Delegates. This allows event to have multiple subscribers.

Carlotacarlotta answered 15/10, 2009 at 2:27 Comment(1)
An event can use a private field, but doesn't have to any more than a property does. Conceptually an event is just the add/remove.Felipa
Y
0

.Net events are just delegates under the hood: They provide some syntactic sugar in the compiler.

You can set/reset a delegate, but you can only add or remove an event handler. The rationale is that you won't care who else subscribes to an event whereas plain delegates are more used in a "callback" scenario.

But at the end of all things they are very very similar.

Some resources:

C# events vs. delegates

Delegates & Events - A short Q&A

Yarvis answered 15/10, 2009 at 2:20 Comment(2)
No, events aren't delegates. Events are add/remove methods, basically. Saying that events are delegates is like saying that properties are fields.Felipa
IMHO properties SHALL behave like fields, exactly like events shall behave as multicast delegates. Else it is misleading to the user of a class since property & field access look similar in the source as do event dispatch and delegate dispatch. This does not mean that a property or event needs to use the default implementation (backing field, backing multicast delegate). It just means "property/field: Get/Set a value without side effects" and "event/delegate: run a callback". With properties / events the language gives you a lot of rope which you can use sensibly or to hang yourself.Yarvis
M
0

I'm new to the java world but I have to admit I'm pretty delighted, but I still miss some C # stuff, so design this pattern that has given me good results, Java experts see some drawback in using this pattern? It only supports 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");
    }
}

Feel free to ask, corrections, suggestions =) Best regards!

Monastic answered 25/3, 2017 at 23:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.