.net事件混乱

时间:2012-04-27 00:37:18

标签: c# .net wpf events

我有一个数据结构类,它是更大的数据/状态类的子代。

内部数据结构在包含的数据发生更改时触发事件。此事件由较大的数据/状态类使用。然后,数据/状态类将触发其自己的事件,以便它可以将其他信息传递给下一个事件处理程序。

Public class Data
{
    //properties and objects go here

    public int Count
    {
        get { return _count; }
        internal set 
        {
            //if the count grew simply set _count
            if (value != _oldCount)
            {
                _oldCount = _count;
                _count = value;
            }
            //if the count shrank then set the count and trigger an event if the count is under 100
            else
            {
                _oldCount = _count;
                _count = value;
                if (_count < 100)
                {
                    CountChanged(this, new EventArgs());
                }
            }
        }
    }
    public event EventHandler CountChanged;
}

上述事件由此事件处理程序

使用
Data.CountChanged += new EventHandler(DataCountChanged);
private void DataCountChanged(object sender, EventArgs e)
{
    DataRemoved(this, e);  //Handle the old event and trigger a new event to pass along more information
}
public event EventHandler DataRemoved;

最后,第二个事件应由另一个事件处理程序处理以完成一些工作。不幸的是,触发第二个事件的调用失败了,通常是NullReferenceException。为什么?

---- ---- EDIT 我知道检查Null会阻止异常。混淆是为什么这个事件首先是空的= D

4 个答案:

答案 0 :(得分:3)

您应始终使用以下模式引发事件以避免空引用和线程问题:

private void DataCountChanged(object sender, EventArgs e)
{
    var dr = DataRemoved;
    if (dr != null)
    {
        dr(this, e);
    }
}

处理程序为null的原因是它应该被视为一个特殊的委托集合。当集合为空时,委托具有空值。当您附加一个或多个处理程序时,该集合不再为空,因此不再为空。

答案 1 :(得分:0)

if(DataRemoved != null && DataRemoved.GetInvocationList().Length > 0)
            {
            }

答案 2 :(得分:0)

为您的活动分配空委托可能不是一个好的设计实践。事件本质上是委托,就像函数指针一样。换句话说,它们就像你班上的其他参考成员一样。除非您为它们分配值或订阅它们,否则它们将是且应该为空。

您获得的空引用异常与声明private MyClass;的原因相同,然后在为其分配值之前尝试使用它。

当您订阅某个活动时,您实际上是在告诉该活动要调用哪个功能。如果您的事件没有至少一个这样的函数指针,它将不存在(NULL)。

答案 3 :(得分:-3)

有一个技巧可以避免空检查:

按如下方式初始化您的活动:

public event YourDelegate MyEvent = delegate { };

这样您就不需要像往常一样调用事件来检查空值:

this.MyEvent("Hi there!");

<强>被修改

澄清:

声明这样的事件:

public event Action MyEvent;

它会自动翻译为:

private Action myEvent;
public event Action MyEvent
{
   add
   {
      this.myEvent += value;
   }
   remove
   {
      this.myEvent -= value;
   }
}

因此初始化这样的事件:

public event Action MyEvent = delegate { };

这是安全的,因为外部代码无法为事件本身指定null。

但是,您可以为声明的类中的事件分配null,但实际发生的是,您将null赋给事件使用的私有委托

来源:Jon Skeet, C# In Depth, Events