从基类调用事件

时间:2015-08-03 12:48:47

标签: c# events inheritance

我有以下情况:

public abstract class SomeBaseClass
{
    public event EventHandler SomeEvent;

    ...
}

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

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

SomeBaseClass有一个需要在基类中调用的事件,但是不能直接从基类调用该事件。为了解决这个问题,我可以覆盖基类中的事件,如下所示:

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

我想这很好,但我的问题是,是否有某种通用方法,或良好做法来实现上述功能?

无法从基类调用事件这一事实表明我不应该首先执行此操作,也许调用事件的责任应仅在SomeBaseClass

4 个答案:

答案 0 :(得分:9)

确实不允许这样做。如果我可以推荐一种替代方法:

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);
    }
}

请注意,我已将事件处理程序的调用移动到拥有类,这是.NET / C#所必需的,因为只有该类可以调用事件处理程序。其次,我首先通过将事件处理程序线程分配给eh来使其安全。

从不隐藏基类'使用new关键字进行活动!当您使用基类时,您将获得意想不到的结果。键入变量的类型或基类调用事件。

答案 1 :(得分:3)

我会远离使用new,主要是因为如果将对象强制转换为基类,代码的行为会有所不同。这是另一种实现方式:

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
    }
}

这样可以提供很大的灵活性。您可以提供一些事件处理实现,并允许实现者完全覆盖基类实现。

答案 2 :(得分:0)

我个人更喜欢使用代表:

   public abstract class SomeBaseClass
    {
        public event EventHandler SomeEvent;
        protected Action<object, EventArgs> SomeEventInvoker;

        public SomeBaseClass()
        {
            SomeEventInvoker = new Action<object, EventArgs>((sender, args) => 
             { if (SomeEvent != null) SomeEvent(sender, args); });
        }
    }

   public class SomeClass : SomeBaseClass
    {
        public SomeClass()
        {
            DoSomething();
        }

        public void DoSomething()
        {                
            SomeEventInvoker(this, new EventArgs());
        }
    }

答案 3 :(得分:0)

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);
   }
}