我正在为C#制作自定义事件,有时它无效。
这就是我发生事件的方式:
private bool isDoorOpen;
public bool IsDoorOpen {
get { return isDoorOpen;}
private set { isDoorOpen = value; DoorsChangeState(this, null);}
}
这些是事件声明:
//events
public delegate void ChangedEventHandler(Elevator sender, EventArgs e);
public event ChangedEventHandler PositionChanged;
public event ChangedEventHandler DirectionChanged;
public event ChangedEventHandler BreaksChangeState;
public event ChangedEventHandler DoorsChangeState;
只要有事件附加方法,这就有效,但如果没有,则抛出空引用异常。我做错了什么?
答案 0 :(得分:10)
调用活动的推荐方法是
var handler = this.DoorsChangeState;
if (handler != null)
handler(this, null);
在本地复制处理程序的原因是在检查null时,在另一个线程上更改事件处理程序。
编辑:发现文章谈论竞争条件。 http://blogs.msdn.com/ericlippert/archive/2009/04/29/events-and-races.aspx答案 1 :(得分:4)
我知道这个问题已经在SO上多次讨论(和回答)。
在这里的某处,我还有以下扩展方法,使这个模式更容易使用:
public static class EventHandlerExtensions
{
public static void FireEvent<T>(this EventHandler<T> handler, object sender, T args) where T : EventArgs
{
var temp = handler;
if (temp != null)
{
temp(sender, args);
}
}
public static void FireEvent(this EventHandler handler, object sender)
{
var temp = handler;
if (temp != null)
{
temp(sender, EventArgs.Empty);
}
}
}
因此,在您的代码中,您可以说:
public bool IsDoorOpen
{
get { return isDoorOpen;}
private set
{
isDoorOpen = value;
DoorsChangeState.FireEvent(this);
}
}
答案 2 :(得分:0)
如果事件在触发时未订阅,则会抛出NullReferenceException。这是正确的行为,而不是你做错了。
你应该检查:
if(DoorsChangeState != null)
{
DoorsChangeState(this, null); // Only fire if subscribed to
}
答案 3 :(得分:0)
在调用事件之前,您必须检查事件是否为null:
if (DoorsChangeState != null)
DoorsChangeState(this, null);
当DoorsChangeState
为空时,表示该事件上没有侦听器。
答案 4 :(得分:0)
您需要检查事件是否已订阅。
我使用这个标准表格来投掷我的所有活动。
var temp = EventName;
if(EventName!= null)
temp(this, null);