答案 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; }
}
事件类似于财产;围绕委托的包装器,只允许添加或删除方法。这样您就无法完全重新分配代理并删除其他人的订阅。
在接口中指定事件时,您所做的就是任何实现类都应该具有事件的add
和remove
方法。事实上,非常类似于在接口上声明属性。
这也是为什么你只能在它声明的类中调用或重新分配事件的原因 - 对类中MyEvent
事件的任何引用都被重新路由以直接使用委托,而在外面该类只能访问add
和remove
方法,而不能直接访问代理。
答案 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);}
}
其中Events
是EventHandlerList
,通常是延迟加载的:
private EventHandlerList events;
protected EventHandlerList Events {
get {
if(events == null) events = new EventHandlerList();
return events;
}
}
或者你可以做任何你喜欢的事情。在合理范围内(注意事件订阅和委托相等/复合代表的预期行为)。
答案 2 :(得分:0)
事件不表示为字段或方法。就类的元数据而言,它们只是事件。
类似地,属性具有特殊标志(尽管这些标记存储为具有众所周知名称的方法)。