Friday, November 30, 2007 - 07:59

Events & Inheritance

I came across something odd the other day concerning events and inheritance.

I have a class which inherits from a TextEdit. I created this derived class so that I could add some behaviour to the Click event, without having to hook up the event for every TextEdit I use - so that I could just myTextEdit instead. My first approach was to hook up a OnClick event handler to the Click event in the constructor:


public myTextEdit()
{
InitializeComponent();
Click += new EventHandler(myTextEdit_Click);
}

void myTextEdit_Click(object sender, EventArgs e)
{
// do stuff
}


But while the code hooking up the event was executed, my event handler was never run. So my second approach was to instead override the eventhandler:


protected override void OnClick(EventArgs e)
{
base.OnClick(e);

// do stuff
}

and this worked perfectly.

But I don't understand why the first approach didn't work. While the two approaches are doing radically different things under the covers, they should amount to much the same thing in the end: the event handler should be fired (since it's the base class that's actually raising the event, not the derived class). Maybe I'm just missing something obvious?

I did a bit of reading, and it seems that the overriding is the 'better' way to go, since if you're creating a derived class you're the publisher of the event, and shouldn't be a subscriber. This totally makes sense, but even they seem to think that either method should work. After all, if I’d overridden the base class without touching the events and event handlers, then instantiated my derived class, and then created a 3rd class and hooked up event handlers in that class to the event, I’d expect them to be fired. How does the internal event firing mechanism differ if the event handlers are hooked up in the derived class rather than a 3rd external class?

The next step, of course, was to write a set of test classes to try this out in a simple demo - and just to confuse the issue, both methods worked! So either my demo wasn't set up correctly, or it only occurs on GUI related .NET methods like OnClick(). I'll keep investigating, and report back if I find anything useful... but in the meantime, if you have any ideas, please leave a comment!

Edit: Okay, I think I've figured out what's happening, thanks to a bit of experimenting and this thread. If you declare an event as virtual, the base class and the derived class each have their own delegate list, which is where the problem comes in. If you have an external class which subscribes to the derived class's event, but doesn't subscribe to the base class's event, then trigger the event in the base class, the event isn't fired in the base class (since the delegate is null), and therefore it derived class's event handler can't react to it. I'm not sure if that is what's happening in this case, since the actual event and the base handlers are declared somewhere within the depths of .NET and DevExpress, but it would make sense - and would explain why my simple demo app works perfectly.

Labels:

0 Comments:

Post a Comment

<< Home