tags:

views:

445

answers:

6

When should one do the following?

class Foo : Control
{
    protected override void OnClick(EventArgs e)
    {
        // new code here
    }
}

As opposed to this?

class Foo : Control
{
    public Foo()
    {
        this.Click += new EventHandler(Clicked);
    }

    private void Clicked(object sender, EventArgs e)
    {
        // code
    }
}
+5  A: 

Overriding rather than attaching a delegate will result in more efficient code, so it is generally recommended that you always do this where possible. For more information see this MSDN article. Here is a pertinent quote:

The protected OnEventName method also allows derived classes to override the event without attaching a delegate to it. A derived class must always call the OnEventName method of the base class to ensure that registered delegates receive the event.

Kent Boogaart
I agree, override ftw
Simucal
Interestingly, the design guidelines state that when creating a virtual OnFoo() method, the corresponding Foo event should be fired even if a descending class doesn't call base.OnFoo()! That'd be pretty awkward to pull off in reality though.
Matt Hamilton
@Matt: private void RaiseFoo( ) { /* Call OnFoo for derived classes */ this.OnFoo( ); /* Raise foo event (works even if base.OnFoo is never call by derived classes) */ ...}protected virtual void OnFoo( ) { /* does nothing */ }
Emperor XLII
+3  A: 

The event is for external subscribers. When you are deriving some control, always override the OnEvent method instead of subscribing to the event. This way, you can be sure when your code is called, because the actual event is fired when you call base.OnEvent(), and you can call this before your code, after your code, in the middle of your code or not at all. You can then also react on return values from the event (i.e. changed properties in the EventArgs object).

OregonGhost
+1  A: 

If you override like Kent Boogaart comments you'll need to be carefull to call back base.OnClick to allow event suscriptions to be called

AlbertEin
A: 

An inherited class should never subscribe to it's own events, or it's base class' events.

Now, if a class has an instance of another, different, class in it, then it can consume that class' events, and determine if it should raise it's own event or not.

For example, I rolled out a MRU List class recently. In it, there was a number of ToolStripMenuItem controls, whose click event I consumed. After that click event was consumed, I then raised my class's event. (see that source code here)

Stephen Wrighton
A: 

Subscribing to the event is intended for a control to monitor events on a different control. For monitoring your own event OnClick is fine. Note, however, that Control.OnClick handles firing those subscribed events, so be sure to call it in your override.

James Curran
+1  A: 

Be aware that (at least in .NET 2.0) I have found a few places in the framework (specifically in the DataTable class) where the OnFoo method is only called when the corresponding Foo event has been handled! This contravenes the framework design guidelines but we're stuck with it.

I've gotten around it by handling the event with a dummy handler somewhere in the class, eg:

public class MyDataTable : DataTable
{
    public override void EndInit()
    {
        base.EndInit();
        this.TableNewRow += delegate(object sender, DataTableNewRowEventArgs e) { };
    }

    protected override void OnTableNewRow(DataTableNewRowEventArgs e)
    {
        base.OnTableNewRow(e);
        // your code here
    }
}
Matt Hamilton
That is interesting, I didn't know that. It is possible to code it like that, which is scary ...
MagicKat