Call an event from a base class

10,048

Solution 1

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.

Solution 2

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.

Solution 3

public delegate void ErrorHandler(string result);
public class BaseClass
{
   public event ErrorHandler OnError;
   protected void RaiseErrorEvent(string result)
   {
     OnError?.Invoke(result);
   }
 }
public class SampleClass:BaseClass
{
   public void Error(string s)
   {
     base.RaiseErrorEvent(s);
   }
}
Share:
10,048

Related videos on Youtube

Mike Eason
Author by

Mike Eason

Updated on August 27, 2022

Comments

  • Mike Eason
    Mike Eason over 1 year

    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?

    • Zohar Peled
      Zohar Peled almost 9 years
      AFAIK, Events are not inherited, so you can't raise the event directly from the derived class, but you can write a protected method in the parent class that will raise the event when called, and call it from the derived class using base.RaiseMyEvent(new EventArgs())
    • Mike Eason
      Mike Eason almost 9 years
      @KhanhTO Yep, I got the error: "Use of keyword 'base' is not valid in this context"
    • Khanh TO
      Khanh TO
      did you try SomeEvent(base, EventArgs.Empty);?
  • Sinatr
    Sinatr almost 9 years
    In C# 6.0 thread-safe event rising is a "simple" SomeEvent?.Invoke(this, e);
  • Patrick Hofman
    Patrick Hofman almost 9 years
    @Sinatr that is nice indeed. Thanks for the useful comment.