Events
From eqqon
(→Events in C#) |
m (→Declaration and what the Compiler does under the Surface) |
||
Line 4: | Line 4: | ||
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. | 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 and what the Compiler does under the Surface == | + | == Declaration of an Event (and what the Compiler does under the Surface) == |
The typical declaration of an event in C# looks like this: | The typical declaration of an event in C# looks like this: | ||
public event <type> <name>; | public event <type> <name>; | ||
- | <type> is a derived type of ''MulticastDelegate'' which is a subtype of ''Delegate''. Examples are ''Action<T>'', '' | + | <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: |
- | The compiler creates a private field with the same name and a pair of public accessors to add and remove delegates | + | |
private <type> <name>; | private <type> <name>; | ||
Line 15: | Line 14: | ||
} | } | ||
- | public void | + | public void remove_<name>(<type> value) |
{ | { | ||
this.<name> = (<type>) Delegate.Remove(this.<name>, value); | this.<name> = (<type>) Delegate.Remove(this.<name>, value); |
Revision as of 19:47, 21 December 2007
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); }
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)