我正在阅读Jon Skeet的this文章,这是我深入了解代表和事件的一部分。
在文章中,他演示了一个没有委托变量支持的事件,并说明了......
...有时候你不想这样做 用简单的委托来支持一个事件 变量。例如,在情况下 那里有很多活动但是 只有少数可能会被订阅 你可以从一些钥匙上得到一张地图 向代表描述事件 目前处理它。这是什么 Windows窗体确实 - 它意味着你 可以举办大量的活动 不浪费大量的记忆 通常只有变量 空值。
我不完全明白他在说什么。有人可以充实这些例子吗?例如,他的意思是“从描述事件的某个键映射到当前处理它的代理”? Windows Forms如何做到这一点?
谢谢!
答案 0 :(得分:5)
您可以自己使用相同的类型 - EventHandlerList
。假设您有100个事件 - 这通常意味着有100个变量,即使没有人订阅过该事件也会占用空间。取而代之的是,EventHandlerList
是位,就像Dictionary<object, EventHandler>
一样 - 它只在您第一次订阅特定事件时在其内部数据结构中创建一个条目。
所以你可能有类似的东西:
// Actual values don't matter; they're just keys
private const string FirstEventKey = "FirstEvent";
private const string SecondEventKey = "SecondEvent";
private readonly EventHandlerList events = new EventHandlerList();
public event EventHandler FirstEvent
{
add { events.AddHandler(FirstEventKey, value); }
remove { events.RemoveHandler(FirstEventKey, value); }
}
public event EventHandler SecondEvent
{
add { events.AddHandler(SecondEventKey, value); }
remove { events.RemoveHandler(SecondEventKey, value); }
}
public void OnFirstEvent(EventArgs e)
{
EventHandler handler = (EventHandler) events[FirstEventKey];
if (handler != null)
{
handler(this, e);
}
}
// Similarly for OnSecondEvent
答案 1 :(得分:0)
我想补充一点,这是我经常看到的东西
// bad code
class MyControl : Control {
public event EventHandler ValueChanged;
private CheckBox checked;
// ...
private void InitializeComponent() {
// ...
checked.CheckedChanged += checked_CheckedChanged;
// ...
}
private void checked_CheckedChanged(object sender, EventArgs e) {
if (ValueChanged != null) {
ValueChanged(sender, e);
}
}
}
我认为这是一种反模式,因为这种方式更快,内存更少,总体上更简单:
class MyControl : Control {
public event EventHandler ValueChanged {
add {
checked.CheckChanged += value;
}
remove {
checked.CheckChanged -= value;
}
}
private CheckBox checked;
// ...
}
答案 2 :(得分:0)
另一种情况是微不足道的情况,其中基类或接口为某些派生类型中永远不会发生的事件提供事件。例如,只读的observable-collection接口可能提供CollectionChangedEvent。持有接口变量的实体将无法使用它来更改集合,但可能有兴趣知道是否/何时更改了集合。这样的实体应该能够使用不可变集合以及可变集合;从它的角度来看,一个不可变的集合应该就像一个可变的集合,没有人在它正在观看时发生变异。
CollectionChangedEvent最合乎逻辑的实现是使add-and -hand-handler方法不做任何事情,没有支持委托字段。调用add-handler方法的外部实体实质上是说“如果此集合发生更改,请给我打电话”。当它调用remove-handler方法时,它基本上是在说“我不再需要知道这个集合是否会改变”。如果集合永远不会改变,那么这些请求可以通过简单地无所事事来兑现。