[英]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();
要调用事件处理程序,您需要做两件事。
您已忽略了在代码中显示第一项。 如果您尚未将事件处理程序连接到事件,则需要这样做。 您可以这样做:
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.