Events
From eqqon
m (→Declaration and what the Compiler does under the Surface) |
(→Fireing the Event) |
||
Line 18: | Line 18: | ||
this.<name> = (<type>) Delegate.Remove(this.<name>, value); | this.<name> = (<type>) Delegate.Remove(this.<name>, value); | ||
} | } | ||
+ | |||
+ | == Fireing the Event == | ||
+ | Consider again our example event | ||
+ | public event <type> <name>; | ||
+ | Fire the event manually: | ||
+ | if (this.<name> != null) this.<name>( <parameters> ); | ||
+ | Fire the event programmatically: | ||
+ | if (this.<name> != null) | ||
+ | foreach (Delegate d in this.<name>.GetInvocationList()) | ||
+ | d.Method.Invoke(d.Target, <parameters>); | ||
== Quick Facts == | == Quick Facts == |
Revision as of 21:35, 21 December 2007
Contents |
Events in C#
An event is just an accessor (+=, -=) to a field holding a MulticastDelegate. The difference between a publicly accessible delegate field and an event are that you cannot overwrite the existing registered delegates, only append or remove. You also cannot reset the private event handler field to null from outside.
Declaration of an Event (and what the Compiler does under the Surface)
The typical declaration of an event in C# looks like this:
public event <type> <name>;
<type> is a derived type of MulticastDelegate which is a subtype of Delegate. Examples are System.Action<T>, System.Windows.Forms.EventHandler, ... etc. There are hundreds of types derived from MulticastDelegate in mscorelib.dll which is -- in my opinion -- really a mess. A small set of simple generic delegates like Action<T>, Action<T1, T2>, ... etc would be enough. Ok let's have a look at what happens under the hood. The compiler creates a private field with the same name and a pair of public accessors to add and remove delegates:
private <type> <name>; public void add_<name>( <type> value){ this.<name> = (<type>) Delegate.Combine(this.<name>, value); } public void remove_<name>(<type> value) { this.<name> = (<type>) Delegate.Remove(this.<name>, value); }
Fireing the Event
Consider again our example event
public event <type> <name>;
Fire the event manually:
if (this.<name> != null) this.<name>( <parameters> );
Fire the event programmatically:
if (this.<name> != null) foreach (Delegate d in this.<name>.GetInvocationList()) d.Method.Invoke(d.Target, <parameters>);
Quick Facts
- Fireing an Event that has not been registered (==null) raises a NullReferenceException. (annoying)
- Registering for the same event twice with the same delegate means that the delegate will be called twice.
- A delegate that has been registered for the same event multiple times must also be unregistered multiple times.
- Unregistering an event that has never been registered (using -= on a null event) has no effect.
- There is no built-in mechanism for preventing event recursions. (see Preventing Recursive Events)