C#事件的内部设计

TOP*_*KEK 3 c#

刚读完Jon Skeet 关于事件和代表文章并得到了一个问题.

让我们首先在代码中声明一个事件

public event EventHandler MyEvent
Run Code Online (Sandbox Code Playgroud)

然后我想以某种方式在代码中提出它

if (MyEvent != null)
    Myevent(this,EvtArgs.Empty);
Run Code Online (Sandbox Code Playgroud)

Jon说,实际上MyEvent看起来像这样:

private EventHandler _myEvent;

public event EventHandler MyEvent
{
    add
    {
        lock (this)
        {
            _myEvent += value;
        }
    }
    remove
    {
        lock (this)
        {
            _myEvent -= value;
        }
    }        
} 
Run Code Online (Sandbox Code Playgroud)

问题是我比较时会发生什么MyEvent != null?正如我其实明白它比较_myEventnull,但我不知道.

Jon*_*eet 5

如果您实现自定义添加/删除访问器,您将无法首先MyEvent与null 进行比较,因为它只是一个事件 - 它没有这样的值,只添加/删除访问器.您必须使用您声明的字段(_myEvent在上面的示例中).

当您使用类似字段的事件时,您只能使用事件名称进行比较,最终(有效地)结束字段和具有相同名称的事件.(编译代码不具有的字段名实际重用事件名称,但它必须看起来就像当你正在编译它.)

请注意使用此:

if (MyEvent != null)
    MyEvent(this,EvtArgs.Empty);
Run Code Online (Sandbox Code Playgroud)

不是线程安全的,因为在检查和调用之间MyEvent可能变为null .你应该使用:

EventHandler handler = MyEvent;
if (handler != null)
{
    handler(this, EventArgs.Empty);
}
Run Code Online (Sandbox Code Playgroud)

另请注意,关于字段式事件锁定的部分this现在稍微过时了; 在C#4中,使用无锁比较交换机制实现线程安全.