Adding one event handler to another
.net, c#, delegates, event-handling
Solution
The problem is that `Delegate`s are immutable.
If you add a handler to an event, it creates a new `Delegate` instance which contains the old handlers and the newly added handler. The old `Delegate` is not modified and is discarded.
When I write, `value.AnEvent += AnEvent`, it adds the `Delegate` containing the current handlers (if any) to the inner class's event. However, changes to the outer class's event are ignored because they don't change the `Delegate` instance that I added to the inner classes event. Similarly, if I remove a handler after setting the `Inner` property, the handler isn't removed from the inner class's event.
There are two correct ways to do this.
I can make my own handler that invokes the wrapper's event, like this:
public event EventHandler AnEvent;
public OtherClass Inner {
get { /* ... */ }
set {
if(Inner != null)
Inner.AnEvent -= Inner_AnEvent;
//...
if(value != null)
value.AnEvent += Inner_AnEvent;
//...
}
}
void Inner_AnEvent(object sender, EventArgs e) {
var handler = AnEvent;
if (handler != null) handler(sender, e);
}
The other way is to make a custom event in the wrapper that adds its handlers to the inner class's event, like this:
EventHandler anEventDelegates
public OtherClass Inner {
get { /* ... */ }
set {
//...
if(value != null)
value.AnEvent += anEventDelegates;
//...
}
}
public event EventHandler AnEvent {
add {
anEventDelegates += value;
if (Inner != null) Inner.AnEvent += value;
}
remove {
anEventDelegates -= value;
if(Inner != null) Inner -= value;
}
}
Note that this is not entirely thread-safe.
I solved this problem myself and am posting the question & answer for the benefit of people with similar problems.
Problem
I have a class which wraps another class and exposes several events from the class it's wrapping. (The instance it wraps can change) I used the following code: ``` public event EventHandler AnEvent; public OtherClass Inner { get { /* ... */ } set { //... if(value != null) value.AnEvent += AnEvent; //... } } ``` However, the events were raised inconsistently. What's wrong with this code?