2

我有一个抽象类 A,它具有检查阈值所需的功能。当违反阈值时,我希望引发一个通知我的事件。我在 Qt 中做过很多次这样的事情,但我似乎无法弄清楚如何将它转移到 C#。这是我目前想到的结构。

namespace N
{
  abstract class A
  {
    public delegate void Notify();
    public event Notify Notifier;
    public abstract void CheckThreshold();
  }

  class B : A
  {
    public override void CheckThreshold()
    {
       Notifier();
    }
  }

  class N
  {
    public AlertMe()
    {
    }
    public static Main()
    {
      var b = new B();
      b.Notifier += new A.Notify(AlertMe);

      b.CheckThreshold();
    }
  }
}
4

5 回答 5

2

通常,您要遵循的表格是这样的:

public event EventHandler<SomeEventArgs> SomeEvent = (s, e) => { };

protected virtual void OnSomeEvent(SomeEventArgs e)
{
    SomeEvent(this, e);
}

所以在你的情况下你可能想要:

abstract class A {

    public event EventHandler<EventArgs> ThresholdExceeded = (s, e) => { };

    protected virtual void OnThresholdExceeded(EventArgs e)
    {
        ThresholdExceeded(e);
    }

    public abstract void CheckThreshold();
}

class B : A {
    public override void CheckThreshold()
    {
        if (/* your condition */) OnThresholdExceeded(new EventArgs());
    }
}

现在有几件事 - EventHandler 类型是一些很好的语法糖,用于制作特定类型的事件。右侧的 lambda 表达式将其初始化为默认处理程序,因此您不必在调用它之前检查它是否为 null。

EventArgs 是特定于事件的信息 - 您没有,但如果您这样做了,您将继承 EventArgs 并放入您的事件接收器需要的任何数据。

public event SomeEventName和对的模式protected virtual void OnSomeEvent由 Microsoft 为 .NET 中的事件规定。您不必遵循这一点,但这是 .NET 程序员想要的。

于 2012-11-30T18:36:59.133 回答
1

您可以在基类 A 中定义一个辅助方法

protected void FireNotification() 
{
    if (Notifier != null)
        Notifier();
}

并从被覆盖的CheckTreshold.

于 2012-11-30T18:06:06.593 回答
1

这段代码有几个问题。

首先,您应该使用 EventHandler 内置委托来定义事件。其次,您不能在定义它的类之外引发事件(这就是为什么您不能使用后代的 Notify() 的原因)。第三,您可以使用模板方法设计模式并更清楚地定义基类与其后代之间的契约,并实现阈值检查的一部分。

最后我完全不明白为什么你需要继承层次结构?也许您可以在一个类中实现所有必需的逻辑?但无论如何,这里的代码可以正确编译和运行:

  abstract class A
  {
    // Avoid defining custom delegate at all because there is a lot of 
    // build-in events for every case, like EventHandler<T>, 
    // Func<T>, Action<T> etc
    // public delegate void Notify();
    public event EventHandler ThreasholdViolated;

    protected void OnThreasholdViolated()
    {
       var handler = ThreasholdViolated;
       if (handler != null)
         handler(this, EventArgs.Empty);
    }

    public abstract void CheckThreshold();
  }

  class B : A
  {
    public override void CheckThreshold()
    {
       OnThreasholdViolated();
    }
  }
于 2012-11-30T19:22:44.570 回答
0

通常的模式是在基类中提供一个受保护的虚拟方法,如http://msdn.microsoft.com/en-us/library/vstudio/9aackb16(v=vs.100).aspx所示。该方法的名称约定是 On[EventName] 并采用事件 args 实例。

还要遵循对委托使用 EventHandler 或 EventHandler 的约定,并提供事件发起者和相应的参数。您可以在http://msdn.microsoft.com/en-us/library/vstudio/ms229011(v=vs.100).aspx中找到更多相关信息。请注意,来自 MSDN 的示例不遵循所有这些约定。

于 2012-11-30T18:30:55.553 回答
-1
public abstract class A
{
    public EventHandler<EventArgs> OnThresholdViolated;

    public abstract void CheckThreshold();
}

public class B : A
{
    public B(EventHandler<EventArgs> alertMe) {
        OnThresholdViolated += alertMe;
    }

    public override void CheckThreshold()
    {
        if (null != OnThresholdViolated)
        {
            OnThresholdViolated(this, EventArgs.Empty);
        }
    }
}

然后使用:

        B b = new B(AlertMe);

        b.CheckThreshold();
于 2012-11-30T18:09:10.620 回答