引文:http://www.cnblogs.com/OpenCoder/archive/2009/09/23/1572646.html
c#事件
了解委托之后,就可以来谈谈事件了,C#事件是什么?
c#事件的定义和委托的声明是如此的相似:
event <委托类型> 事件名
例子:public event CheckDelegate checkEvent;
上面的例子声明了个事件叫checkEvent你会发现它只比声明委托实例前多了个关键字event
声明了事件后就可以实例化事件,注册函数到事件,解除事件函数注册其方法和委托的步骤如出一辙:
例子:checkEvent+=new CheckDelegate(CheckMod);//将函数CheckMod注册到事件checkEvent上
checkEvent+=CheckMod;//.net 2.0开始支持这种方法
checkEvent-=newCheckDelegate(CheckMod);//将函数CheckMod解除对事件checkEvent的注册
checkEvent-=CheckMod;//.net 2.0开始支持这种方法
从种种迹象都可以看出事件和委托实例是那么的相似,那么为什么不直接用委托还要用到事件呢?其实事件就是对委托的封装,就如同c#类中属性对字段的封装一样,其封装后可以在委托上封装更复杂的逻辑,下面我们来看c#中事件的两种声明方式,来了解事件对委托的封装
隐式声明事件
这种方式声明事件很简单,就如同声明委托实例一样:
event <委托类型> 事件名;
例子:public event CheckDelegate checkEvent;
我们用反射机制来看看这样声明的事件里面装的到底是什么东西
我们可以看到在事件被编译后自动生成了个private的委托实例checkEvent和两个函数add_checkEvent和remove_checkEvent,这两个函数分别对应事件的+=/-=操作,另外可以看到在声明了事件后的确是产生了一个和事件同名私有的委托实例checkEvent,对事件的+=/-=操作都会反映在这个同名委托实例checkEvent上,所以可以在定义事件的类里面直接调用checkEvent()来执行注册函数和对checkEvent使用=号重新赋值,实际上这里操作的并不是checkEvent事件,而操作的是同名委托实例checkEvent,因此隐式声明的事件,其实就是由一个委托实例和两个函数封装而成,所有的操作最终都反映在委托实例上。
(这里我补充下我的个人理解:事实上在一个类的内部是无法定义一个事件后又定义一个和事件同名的委托实例的,如果你在本例中尝试再定义CheckDelegate checkEvent,编译的时候会报错并提示已经定义了名叫checkEvent的委托,原因是因为事件本来就是一种特殊的委托实例(不管是隐式或显式声明的事件都是这样),因此定义和事件同名的委托实例会报错,所以我个人认为.net在编译的时候会把隐式声明的事件编译成为委托实例(和事件同名),本例中的checkEvent事件在编译后也不再是事件转而被编译成了checkEvent委托实例,否则又怎么可能在定义事件的类的内部可以执行事件和对事件赋值呢(这里大家可以看看我给的显式声明事件的例子,那里面有说到),唯一的解释就是隐式声明的事件其实就是委托实例)显式声明事件
其实显示声明事件就是要自己来手动实现隐式声明事件的一个委托实例
和两个函数:
event <委托类型> 事件名
{
add
{
//将函数注册到自己定义的委托实例
}
remove
{
//解除函数对自己定义的委托实例的注册
}
}
例子:private CheckDelegate _checkDelete;
public event CheckDelegate checkEvent
{
add
{
_checkDelete = Delegate.Combine(_checkDelete, value) as CheckDelegate;
}
remove
{
_checkDelete = Delegate.Remove(_checkDelete, value) as CheckDelegate;
}
//Delegate.Combine和Delegate.Remove是.net库函数,作用是合并委托实例注册函数和移除委托实例注册函数并返回合并和移除后的委托实例,具体解释请查阅MSDN
我们再用反射机制查看显式声明事件编译后的代码
可以看到显示声明事件的代码编译后和隐式声明事件的代码几乎相同,只不过这里我们自己定义了事件操作委托实例_checkDelete。另外显式声明的事件不支持直接调用,就算在定义事件的类里面也不能直接调用显式声明的事件(checkEvent();//这样会报错),应该调用事件委托实例(_checkDelete();)。
参考博客:http://www.tracefact.net/CSharp-Programming/Delegates-and-Events-in-CSharp.aspx
简书代码的阅读性还是很差的。不适合写有含有代码的文章