.Net事件&委托备忘
委托
public delegate xxxx 定义会生成一个委托类的定义,
该类的主要属性是MethodInfo,Target(当Method是静太方法时Target为null)
对委托的执行是通过MethodInfo.Invoke进行反射调用.
该类继承自MulticastDelegate而MulticastDelegate又继承自Delegate
Delegate定义了Combine与Remove两个操作,这两个操作的具体实现是在MulticastDelegate中,MulticastDelegate采用链表形式保留委托链,事件本质上就是对委托的封装
事件可以使用两种方式定义
public delegate void EventHandle()
1.声明方式
public event EventHandle Click
2.属性方式
private static object Event_Click=new object();
public event Click
{
add{...}
remove{...}
}
说明
第一种方式编译后形成如下类似的代码
private EventHandle _Click
public event EventHandle Click
{
add
{...
_Click=Delegate.Combine(ad2, value);
.....
}
remove
{
....
_Click=Delegate.Remove(ad2, value);
....
}
}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
private EventHandler SomeEvent1; // Events public event EventHandler SomeEvent { add { EventHandler handler2; EventHandler someEvent = this.SomeEvent1; do { handler2 = someEvent; EventHandler handler3 = (EventHandler) Delegate.Combine(handler2, value); someEvent = Interlocked.CompareExchange<EventHandler>(ref this.SomeEvent1, handler3, handler2); } while (someEvent != handler2); } remove { EventHandler handler2; EventHandler someEvent = this.SomeEvent1; do { handler2 = someEvent; EventHandler handler3 = (EventHandler) Delegate.Remove(handler2, value); someEvent = Interlocked.CompareExchange<EventHandler>(ref this.SomeEvent1, handler3, handler2); } while (someEvent != handler2); } }
上面的代码do{}while(..)是考虑并发时确保每对this.SomeEvent1附值串行进行,Interlocked.c(v0,v1,v2) 会比较v0是否等于v2,如果相等(即进行Combin后this.SomeEvent1没有被其他线程绑定过), 则将v1附值给v0
否则重新绑定,不管v0是否等于v2 interlocked.cxx(v0,v1,v2) 反回的是原v0的值(v0的旧值)
第二种方式内部使用EventHandleList保存,EventHandleList实质上是一个链表实现,在EventHandleList的实现中,绑定到不同事件的处理过程通过key来检索,
绑定到同一个事件的处理过程还是使用委托链来保存.
为什么说使用属性方式实现比较节省内存
原因在于使用属性方式时,定义的key是private static object Eventxxx=new object(); 该字段使用的是static,这样当该组件/控件被大量实例化时他们只使用同一个对象(当然每个实例有一个自己的EventHandleList),而采用声明方式定义时每个实例都会有一组private EventHandle xxx 字段,而每个字段占用4个字节,当组件/控件有大量事件并创建很多实例时(参考下面winform截图),其内存消耗势必比使用属性方式多,
参考资料:
C# 委托链,Delegate.Combine与Delegate.Remove 深究。
也谈事件(Event)
NET 相关问题: 事件存取器
http://www.cnblogs.com/artech/tag/Event/
事件与委托有别, delegate 与 Delegate 相异
EventHandlerList类型内部存储示意图
C#综合揭秘——深入分析委托与事件
http://topic.csdn.net/u/20090710/10/695cf504-f558-425b-b728-723b6d9232ab.html