【问题标题】:public Event in abstract class抽象类中的公共事件
【发布时间】:2015-04-23 18:01:24
【问题描述】:

我在抽象类中声明了事件:

public abstract class AbstractClass
{
    public event Action ActionEvent;
}

public class MyClass : AbstractClass
{
    private void SomeMethod()
    {
        //Want to access ActionEvent-- Not able to do so
        if (ActionEvent != null)
        {
        }

    }
}

我想在派生中访问这个基类事件。此外,我想在 MyClass 的其他派生类中访问此事件:

MyClass.ActionEvent += DerivedMethod()

请帮助我了解如何处理抽象类中定义的事件。

【问题讨论】:

  • 你应该可以访问它,你只是在派生类中不正确地访问它。它必须是连线的一部分,即ActionEvent += Myhandler;
  • @EugenePodskal OP 没有询问如何在派生类中引发基类事件。
  • 事件主要面向“外部”消费者,而不是派生类。

标签: c# events delegates action abstract-class


【解决方案1】:

一个经常使用的模式如下所示(你会在System.Windows.Forms命名空间的类中看到很多)。

public abstract class MyClass
{
    public event EventHandler MyEvent;

    protected virtual void OnMyEvent(EventArgs e)
    {
        if (this.MyEvent != null)
        {
            this.MyEvent(this, e);
        }
    }
}

然后您可以在这样的派生类中使用它,可选择扩展行为:

public sealed class MyOtherClass : MyClass
{
    public int MyState { get; private set; }

    public void DoMyEvent(bool doSomething)
    {
        // Custom logic that does whatever you need to do
        if (doSomething)
        {
            OnMyEvent(EventArgs.Empty);
        }
    }

    protected override void OnMyEvent(EventArgs e)
    {
        // Do some custom logic, then call the base method
        this.MyState++;

        base.OnMyEvent(e);
    }
}

【讨论】:

  • +1,你偷了我的答案。 :-) 您可能还想提到 OnMyEvent 可以在派生类中被覆盖,而不是从另一个 …MyEvent 方法调用它(只要覆盖方法仍然调用基类的实现)。
  • 问题是关于从抽象类发布事件而不是使用它。
【解决方案2】:

这种方法可能很危险,请参阅下面的更好的方法

事件只能从声明类中的 引发(或明显地检查是否为 null)。这种保护扩展到派生类。

因此,解决方案是重新声明事件作为基类中抽象事件的实现。然后您仍然可以根据需要通过基类引用使用它,并在派生类中提升/使用它:

public abstract class AbstractClass
{
    public abstract event Action ActionEvent;
}

public class MyClass : AbstractClass
{
    public override event Action ActionEvent;

    private void SomeMethod()
    {
        //Want to access ActionEvent-- Now you can!
        if (ActionEvent != null)
        {
        }

    }
}

正确方法

MSDN 建议编译器可能无法正确处理此方法。相反,您应该提供 protected 方法,以便派生类可以检查 null、调用事件等:

public abstract class AbstractClass
{
    public event Action ActionEvent;
    protected bool EventIsNull()
    {
        return ActionEvent == null; 
    }
}

public class MyClass : AbstractClass
{
    private void SomeMethod()
    {
        //Want to access ActionEvent-- Now you can!
        if (!EventIsNull())
        {}
    }
}

【讨论】:

  • 或者在基类中添加一个空值检查方法,然后在派生类中使用。
  • @Asad 当然,但你不能用纯抽象基类来做到这一点
  • 抽象基类仍然可以有具体方法。它只是无法实例化。
  • “纯抽象”是什么意思?你说的是接口吗?
  • @Asad 纯抽象将是所有可能的东西都被标记为抽象的地方。它与接口之间的唯一区别是纯抽象类可以具有数据成员(尽管有些人会争辩说此时它不再是纯的)。另外,您可以从接口乘以继承:)
猜你喜欢
  • 2018-08-25
  • 2015-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-14
  • 2015-07-19
  • 2015-07-08
相关资源
最近更新 更多