为什么在null事件引用上调用+运算符会初始化一个事件?

时间:2015-07-28 19:41:07

标签: c#

我在这里遗漏了什么吗?如何通过运算符更改null事件引用?

class Foo
{

    public event EventHandler<EventArgs> anEvent;
    public Foo()
    {
        Console.WriteLine(anEvent == null); // true
        anEvent += (sender, args) => { var i = 0; };
    }

    public static void Main(String[] args)
    {
        var a = new Foo();
        Console.WriteLine(a.anEvent == null); // false
        Console.ReadKey();
    }

}

1 个答案:

答案 0 :(得分:5)

这实际上会对代码进行一些编译器更改。编译时,它会在anEvent周围创建一个包装器,用于添加/删除处理程序,与属性的工作方式非常相似。例如,在您的类中,编译时,您会看到(或多或少):

class Foo
{
    private EventHandler<EventArgs> anEvent;

    public void add_anEvent(EventHandler<EventArgs> delegateToAdd)
    {
        //some code to make this safe, but basically calls-ish:
        anEvent = System.Delegate.Combine(anEvent, delegateToAdd);
    }

    public Foo()
    {
        Console.WriteLine(anEvent == null); // true

        //your += operator is converted to a call to "add_Event" instead
        add_anEvent((sender, args) => { var i = 0; };);
    }
}

虽然过度简化了底层线程安全代码,但这演示了如何通过返回的System.Delegate.Combine method处理null案例:

  

一个新的委托,它有一个连接调用列表   按顺序调用 a b 的列表。如果 b null ,则返回 a ,   如果 a 是空引用,则返回 b ,如果是,则返回空引用    a b 都是空引用。

编辑:您可以在此处阅读addremove个事件访问者:https://msdn.microsoft.com/en-us/library/aa664456%28v=vs.71%29.aspx

此页面是关于实现自定义事件访问器的,但该页面上可能相关的段落可能是:

  

每个add-accessor-declaration和remove-accessor-declaration   对应于具有事件的单个值参数的方法   type和void返回类型。事件的隐含参数   访问者被命名为值。在事件分配中使用事件时   使用适当的事件访问器。具体来说,如果   赋值运算符是+ =然后使用add访问器,如果是   赋值运算符是 - =然后使用删除访问器。

即使您没有提供自定义addremove实现,编译器也会为您填写一个基本的实现。 (就像你有空getset属性一样,编译器填充一个基本的属性。在这个意义上,&#34; null&#34;通过调用这些方法为您处理案例;您不能直接null事件字段上操作。