事件内部:在.net中,事件如何在内部表示?

时间:2010-04-15 10:56:33

标签: c# .net

3 个答案:

答案 0 :(得分:6)

如果输入:

public event EventHandler MyEvent;

编译器生成的是(简化)这个:

// declares a normal delegate of type 'EventHandler'
private EventHandler _myEvent;

// declares 'add_MyEvent' and 'remove_MyEvent' methods similar to a property
public event EventHandler MyEvent {
    add { _myEvent += value; }
    remove { _myEvent -= value; }
}

事件类似于财产;围绕委托的包装器,只允许添加或删除方法。这样您就无法完全重新分配代理并删除其他人的订阅。

在接口中指定事件时,您所做的就是任何实现类都应该具有事件的addremove方法。事实上,非常类似于在接口上声明属性。

这也是为什么你只能在它声明的类中调用或重新分配事件的原因 - 对类中MyEvent事件的任何引用都被重新路由以直接使用委托,而在外面该类只能访问addremove方法,而不能直接访问代理。

答案 1 :(得分:2)

@ thecoop的答案非常好地描述了“类似田野的事件”(注意“简化”警告) - 但请注意,实际上事件可以以任何你喜欢的方式实施。所有事件定义都是add / remove访问者对(这就是为什么它可以在接口上定义,就像属性一样)。

例如,对于sparce事件,以下情况可能很常见:

private static readonly object FooKey = new object(), BarKey = new object();

public event EventHandler Foo {
    add {Events.AddHandler(FooKey, value);}
    remove {Events.RemoveHandler(FooKey, value);}
}
public event MouseClickEventHandler Bar {
    add {Events.AddHandler(BarKey, value);}
    remove {Events.RemoveHandler(BarKey, value);}
}

其中EventsEventHandlerList,通常是延迟加载的:

private EventHandlerList events;
protected EventHandlerList Events {
    get {
        if(events == null) events = new EventHandlerList();
        return events;
    }
}

或者你可以做任何你喜欢的事情。在合理范围内(注意事件订阅和委托相等/复合代表的预期行为)。

答案 2 :(得分:0)

事件不表示为字段或方法。就类的元数据而言,它们只是事件。

类似地,属性具有特殊标志(尽管这些标记存储为具有众所周知名称的方法)。