Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call an event from a base class

I have the following scenario:

public abstract class SomeBaseClass
{
    public event EventHandler SomeEvent;

    ...
}

public class SomeClass : SomeBaseClass
{
    public void DoSomething()
    {
        //TODO

        if (SomeEvent != null)
            SomeEvent(this, EventArgs.Empty);
    }
}

SomeBaseClass has an event which needs to be called in a base class, however this it isn't possible to directly call the event from a base class. To get around this, I can override the event in the base class, like so:

public class SomeClass : SomeBaseClass
{
    new public event EventHandler SomeEvent;

This is fine I guess, however my question is whether there is some kind of universal method, or good practice for implementing the functionality above?

The fact that it isn't possible to call an event from a base class suggests that I shouldn't really be doing this in the first place, perhaps the responsibility of calling the event should be only in SomeBaseClass?

like image 469
Mike Eason Avatar asked Aug 03 '15 12:08

Mike Eason


2 Answers

That isn't allowed indeed. If I may recommend an alternative approach:

public abstract class SomeBaseClass
{
    public event EventHandler SomeEvent;

    protected void RaiseSomeEvent(EventArgs e)
    {
        var eh = SomeEvent;
        if (eh != null)
            eh(this, e);
    }
}

public class SomeClass : SomeBaseClass
{
    public void DoSomething()
    {
        //TODO
        RaiseSomeEvent(EventArgs.Empty);
    }
}

Note that I have moved the invocation of the event handler to the owning class, this is required by .NET / C# since only that class can invoke the event handler. Second, I have made the event handler thread safe by assigning it to eh first.

Never hide the base class' event by using the new keyword! You will get unexpected results when you use the base class' type as type for a variable or when the base class invokes the event.

like image 86
Patrick Hofman Avatar answered Oct 07 '22 23:10

Patrick Hofman


I would stay away from using new mainly because code will behave differently if an object is cast to the base class. Here's an alternative implementation:

public abstract class SomeBaseClass
{
    public virtual event EventHandler SomeEvent;

    protected virtual void HandleSomeEvent()
    {
        var ev = SomeEvent; // Localize event field used
        if (ev != null)
        {
            ev(this, EventArgs.Empty);
        }
    }
}

public class SomeClass : SomeBaseClass
{
    public override event EventHandler SomeEvent
    {
        add { base.SomeEvent += value; }
        remove { base.SomeEvent -= value; }
    }

    protected override void HandleSomeEvent()
    {
        base.HandleSomeEvent();
        // ... My own code here
    }
}

This allows for a great deal of flexibility. You can provide some implementation of event handling as well as allow the implementer to completely override the base class implementation.

like image 36
Candide Avatar answered Oct 07 '22 23:10

Candide