Delegate is a function pointer. It holds the reference of one or more methods at runtime. Delegate is independent and not dependent on events. An event is dependent on a delegate and cannot be created without delegates.
Multicast delegates help to invoke multiple callbacks. Events encapsulate delegate and implement publisher and subscriber model.
countable noun. A delegate is a person who is chosen to vote or make decisions on behalf of a group of other people, especially at a conference or a meeting.
The keyword event
is a scope modifier for multicast delegates. Practical differences between this and just declaring a multicast delegate are as follows:
event
in an interface.public event
).As a matter of interest, you can apply +
and -
to multicast delegates, and this is the basis of the +=
and -=
syntax for the combination assignment of delegates to events. These three snippets are equivalent:
B = new EventHandler(this.MethodB);
C = new EventHandler(this.MethodC);
A = B + C;
Sample two, illustrating both direct assignment and combination assignment.
B = new EventHandler(this.MethodB);
C = new EventHandler(this.MethodC);
A = B;
A += C;
Sample three: more familiar syntax. You are probably acquainted with the assignment of null to remove all handlers.
B = new EventHandler(this.MethodB);
C = new EventHandler(this.MethodC);
A = null;
A += B;
A += C;
Like properties, events have a full syntax that no-one ever uses. This:
class myExample
{
internal EventHandler eh;
public event EventHandler OnSubmit
{
add
{
eh = Delegate.Combine(eh, value) as EventHandler;
}
remove
{
eh = Delegate.Remove(eh, value) as EventHandler;
}
}
...
}
...does exactly the same as this:
class myExample
{
public event EventHandler OnSubmit;
}
The add and remove methods are more conspicuous in the rather stilted syntax that VB.NET uses (no operator overloads).
From the technical standpoint, other answers have addressed the differences.
From a semantics perspective, events are actions raised by an object when certain conditions are met. For example, my Stock class has a property called Limit, and it raises an event when the stock prices reaches the Limit. This notification is done via an event. Whether anyone actually cares about this event and subscribes to it is beyond the concern of the owner class.
A delegate is a more generic term to describe a construct similar to a pointer in C/C++ terms. All delegates in .Net are multicast delegates. From a semantics perspective, they are generally used as a kind of input. In particular, they are a perfect way to implement the Strategy Pattern. For example, if I want to sort a List of objects, I can provide a Comparator strategy to the method to tell the implementation how to compare two objects.
I have used the two methods in production code. Tons of my data objects notify when certain properties are met. Most basic example, whenever a property changes, a PropertyChanged event is raised (see INotifyPropertyChanged interface). I have used delegates in code to provide different strategies of turning certain objects into string. This particular example was a glorified ToString() list of implementations for a particular object type to display it to users.
Events are syntactical sugar. They are delicious. When I see an event, I know what to do. When I see a delegate, I'm not so sure.
Combining events with interfaces (more sugar) makes for a mouth watering snack. Delegates and pure virtual abstract classes are much less appetizing.
Events are marked as such in the metadata. This allows things like the Windows Forms or ASP.NET designers to distinguish events from mere properties of delegate type, and provide appropriate support for them (specifically showing them on the Events tab of the Properties window).
Another difference from a property of delegate type is that users can only add and remove event handlers, whereas with a property of delegate type they can set the value:
someObj.SomeCallback = MyCallback; // okay, replaces any existing callback
someObj.SomeEvent = MyHandler; // not okay, must use += instead
This helps to isolate event subscribers: I can add my handler to an event, and you can add your handler to the same event, and you won't accidentally overwrite my handler.
Edit#1 When would you use delegates over events and vs.versa? Please state your real world experience with both, say in the production code.
When I design my own APIs, I define delegates which are passed as parameters to methods, or to the constructors of classes:
Predicate
and Action
delegates are passed to the .Net generic collection classes)These delegates are generally non-optional at run-time (i.e. mustn't be null
).
I tend not to use events; but where I do use events, I use them for optionally signalling events to zero, one, or more clients that might be interested, i.e. when it makes sense that a class (e.g. the System.Windows.Form
class) should exist and run whether or not any client has added an event handler to its event (e.g. the form's 'mouse down' event exists, but it's optional whether any external client is interested in installing an event handler onto that event).
Although events are typically implemented with multicast delegates, there is no requirement that they be used in such fashion. If a class exposes event, that means the class exposes two methods. Their meanings are, in essence:
The most common way for a class to handle an event it exposes is to define a multicast delegate, and add/remove any delegates that get passed to the above methods but there is no requirement that they work that way. Unfortunately, the event architecture fails to do some things that would have made alternative approaches much cleaner (e.g. have the subscription method return a MethodInvoker, which would be kept by the subscriber; to unsubscribe an event, simply invoke the returned method) so multicast delegates are by far the most common approach.
to understand the differences you can look at this 2 examples
Exemple with Delegates (Action in this case that is a kind of delegate that doen't return value)
public class Animal
{
public Action Run {get; set;}
public void RaiseEvent()
{
if (Run != null)
{
Run();
}
}
}
to use the delegate you should do something like this
Animale animal= new Animal();
animal.Run += () => Console.WriteLine("I'm running");
animal.Run += () => Console.WriteLine("I'm still running") ;
animal.RaiseEvent();
this code works well but you could have some weak spots.
For example if I write this
animal.Run += () => Console.WriteLine("I'm running");
animal.Run += () => Console.WriteLine("I'm still running");
animal.Run = () => Console.WriteLine("I'm sleeping") ;
with the last line of code I had override the previous behaviors just with one missing +
(I have used +
instead of +=
)
Another weak spot is that every class that use your Animal
class can raise RaiseEvent
just calling it animal.RaiseEvent()
.
To avoid this weak spots you can use events
in c#.
Your Animal class will change in this way
public class ArgsSpecial :EventArgs
{
public ArgsSpecial (string val)
{
Operation=val;
}
public string Operation {get; set;}
}
public class Animal
{
public event EventHandler<ArgsSpecial> Run = delegate{} //empty delegate. In this way you are sure that value is always != null because no one outside of the class can change it
public void RaiseEvent()
{
Run(this, new ArgsSpecial("Run faster"));
}
}
to call events
Animale animal= new Animal();
animal.Run += (sender, e) => Console.WriteLine("I'm running. My value is {0}", e.Operation);
animal.RaiseEvent();
Differences:
notes
EventHandler is declared as the following delegate:
public delegate void EventHandler (object sender, EventArgs e)
it takes a sender (of Object type) and event arguments. The sender is null if it comes from static methods.
You can use also EventHAndler
instead this example that use EventHandler<ArgsSpecial>
refer here for documentation about EventHandler
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With