繁体   English   中英

在C#中使用事件处理程序

[英]Using an Event Handler in C#

我正在尝试观察c#中的值,并在其更改时触发一个函数。 根据阅读示例,我有:

//事件观察者

private int _currentFrame =1;
public event System.EventHandler FrameChanged;

protected virtual void OnFrameChanged()
{
    if (FrameChanged != null) FrameChanged(this, EventArgs.Empty);
}

public int Age
{
    get
    {
        return _currentFrame;
    }

    set
    {
        //#3
        _currentFrame = value;
        OnFrameChanged();
    }
}

在我的主要职能中:

_currentFrame += _currentFrame;

据我了解,这应该触发事件观察器,但事实并非如此。 我错过了什么?

谢谢。

您尚未为FrameChanged分配任何事件。

yourInstance.FrameChanged+= () => DoSomething();

要调用事件处理程序,您需要做两件事。

  1. 您需要将事件处理程序挂接到事件上
  2. 您需要触发事件

您已忽略了在代码中显示第一项。 如果您尚未将事件处理程序连接到事件,则需要这样做。 您可以这样做:

someObject.FrameChanged += SomeObjectFrameChanged;

...

private void SomeObjectFrameChanged(object sender, EventArgs e)
{
    ... code here
}

第二个在表面上看起来不错,该属性调用OnFrameChanged。

顺便说一句,不建议您使用OnFrameChanged实现事件处理程序触发方法,您应该使用以下模板:

protected virtual void OnFrameChanged()
{
    var evt = FrameChanged;
    if (evt != null) evt(this, EventArgs.Empty);
}

进行此更改的原因是,将事件值提升为局部变量是因为,如果您处于多线程环境中,则在检查事件至少具有一个事件处理程序( != null )之后,另一个线程可以取消订阅该事件处理程序!= null最后一个事件处理程序。 细细挑选,但您仍然应该更改它。

在C#6中,您可以将上述方法更改为:

protected virtual void OnFrameChanged()
{
    FrameChanged?.Invoke(this, EventArgs.Empty);
}

因为这将做所有相同的事情。


但是在这里,我们来看看您的代码和期望中的真正错误:

_currentFrame += _currentFrame;

您希望这会触发您的事件,但这是不正确的。

您正在直接访问后备字段,该字段将绕过属性中的所有代码,因此此处没有调用OnFrameChanged代码,因此不会触发该事件。

相反,您应该访问该属性

Age += Age;

次要挑剔#2是您应确保仅在属性实际更改时才触发PropertyChanged

Age = 1;
Age = 1; // did not change, do not fire PropertyChanged

因此,您应该像这样实现属性设置器:

set
{
    if (_currentFrame == value) return;

    //#3
    _currentFrame = value;
    OnFrameChanged();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM