EventArgs类背后的基本原理

时间:2009-07-17 08:41:41

标签: c# .net events

我正在学习C#中的事件,并了解EventArgs类包含有关该事件的数据。但我很难理解为什么EventArgs是必要的。

例如,在this MSDN example中,WakeMeUp课程无法从{{1}的字段中读取所有必要数据(snoozePressednrings) }?如果它可以设置它们,为什么它也不能得到它们?

6 个答案:

答案 0 :(得分:11)

EventArgs类的好处(我认为)主要是这两个:

  • 您可以在不改变事件签名的情况下将成员添加到EventArgs类
  • 从对象实例
  • 断开传递给事件处理程序的信息

甚至可能是提升事件的对象没有公开EventArgs中包含的信息。

当然,在某些情况下看起来有点矫枉过正,但我​​认为同样的力量在这里是件好事;如果你知道一个事件是如何运作的,你就会知道其他事件是如何运作的。

答案 1 :(得分:9)

EventArgs类是必要的,因为如果您希望将事件扩展为将来提供更多信息,那么使用原始事件的原始方法签名的所有客户端都会遇到可移植性问题。

例如,

public void IHandleEventVersion1(string p1, int p2)
{
    ....
}

现在,您希望在上面的事件EventVersion1中提供更多信息(您希望包含char)。然后,您必须强制客户端重写其事件处理以匹配您的新要求,如下所示:

public void IHandleEventVersion1(string p1, int p2, char p2)
{
    ...
}

在尝试提供更多信息时,看看它会变得多么尴尬?

因此,EventArgs类提供了一个通用的设计模式来编程,允许您和我快速扩展我们想要为事件提供的数据。

事件框架的一般编码模式是这样的:

基本事件处理策略

  1. 定义您班级的消费者可以订阅的event
  2. 定义事件声明的delegate签名(是的,您也可以使用EventHandler的.NET 2.0通用版本,即EventHandler<TEventArgs>
  3. 为继承者提供protected virtual方法以覆盖以响应基类中引发的事件
  4. 在声明事件的基类中,提供实际引发事件的protected方法的基本实现。

    public class MyClass
    {
        public event EventHandler  /* (point 2) */ MyEvent; /* (point 1) */
    
        // (point 3 + 4)
        protected virtual void OnMyEvent()
        {
            EventHandler temp = MyEvent;
            if (temp != null)
                temp(this, EventArgs.Empty);
        }
    
        public void SomeMethodThatWillRaiseTheEvent()
        {
            ....
            OnMyEvent();
        }
    }
    

答案 2 :(得分:6)

EventArgs适用于:

  • 向您显示事件发生时的状态
  • 通过提供有关活动的信息来提高事件处理代码的性能,而无需查询“第三方”
  • 包含未引发事件的对象公开的数据

要扩展第一点....在你被调用的事件处理程序和你从引发事件的对象中读取状态之间,其他事情可能已经发生,这将状态完全改变为其他东西。在这种情况下,您将响应警报已关闭的AlarmClock上的“AlarmHasGoneOff”事件。

还可以响应“其他地方”引发的事件 - 通过各种不同的机制在另一台机器上的另一个进程/ appdomain /进程中进行响应。如果你不得不回到那个“其他地方”来获取你需要的信息,这可能需要几秒钟(或更少,或更多!),通过EventArgs或派生类传递有用/必需的数据是一个巨大的性能改善。

答案 3 :(得分:2)

EventArgs中传递的数据不一定在生成事件的对象的属性中可用。例如,在MouseDown事件上,MouseEventArgs包含有关当前鼠标位置的信息。生成该事件的对象可能甚至不存储任何易变的东西。

答案 4 :(得分:2)

您不必将EventArgs.Empty传递给处理程序。您可以传递任何派生类。当指定事件处理程序将EventArgs作为参数时,这意味着没有始终可用的特定参数,但您可能希望传递自己的参数以获取额外信息。

答案 5 :(得分:1)

遵循标准模式可以获得的另一个好处是,使用提供事件的类的人可以连接常见的事件处理程序:

public SomeWinFormClass() { 
  InitializeComponent();
  _yourClassInstance = new YourClass();
  someButton.Click += SomethingICareAboutHappened;
  _yourClassInstance.YourEvent += SomethingICareAboutHappened;
}

private void SomethingICareAboutHappened(object sender, EventArgs e)
{
  // do something -- logging, signaling a handle someone's 
  // waiting for, etc.
}

不必声明所有自己的自定义委托来声明你的事件也很好。如果您使用EventHandler<TEventArgs>来声明YourEvent,我认为您不会侥幸逃脱,尽管您似乎应该能够这样做。