C#事件机制初次接触 http://blog.csdn.net/fenghao_5555/archive/2007/08/23/1756424.aspx
2011-03-07 09:56
459 查看
C#是微软出品的新一代编程语言是VS.NET工具集中的主打语言,C#的一个重要特性之一就是支持“事件(Event)”。在C#中为一个类添加事件支持是非常简单的:
打开VS.NET,新建一个C# Console Application,执行“项目”->“添加类”菜单功能,添加一个“MyClass”类:
using System;
namespace ConsoleApplication1
{
//声明一个delegate
public delegate void EventHandler();
/// ///测试C#的event机制。
/// public class MyClass
{
//声明一个成员变量来保存事件句柄(事件被激发时被调用的delegate)
private EventHandler m_Handler = null;
//激发事件
public void FireAEvent()
{
if(m_Handler != null)
{
m_Handler();
}
}
//声明事件
public event EventHandler AEvent
{
add//添加访问器
{
//注意,访问器中实际包含了一个名为value的隐含参数
//该参数的值即为客户程序调用+=时传递过来的delegate
Console.WriteLine("AEvent add 被调用,value的HashCode为:" + value.GetHashCode());
if(value != null){m_Handler = value;};//设置m_Handler域保存新的handler
}
remove//删除访问器
{
Console.WriteLine("AEvent remove 被调用,value的HashCode为:" + value.GetHashCode());
if(value == m_Handler){m_Handler = null;}//置m_Handler为null,该事件将不再被激发
}
}
public MyClass()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
}
}
然后在主文件Class1.cs中输入如下代码:
using System;
namespace ConsoleApplication1
{
/// /// Class1 的摘要说明。
/// class Class1
{
/// ///应用程序的主入口点。
/// [STAThread]
static void Main(string[] args)
{
//
// TODO: 在此处添加代码以启动应用程序
//
//实例化一个MyClass的对象Obj
MyClass Obj = new MyClass();
//基于MyEventHandler()函数定义一个EventHandler
EventHandler MyHandler = new EventHandler(MyEventHandler);
Console.WriteLine("MyHandler的HashCode为:"+MyHandler.GetHashCode());
Console.WriteLine();
//预定事件
Console.WriteLine("Obj.AEvent += Myhandler 被调用");
Obj.AEvent += MyHandler;
//激发事件
Console.WriteLine("Main函数激发Obj的AEvent事件!");
Obj.FireAEvent();
//撤消事件
Console.WriteLine("Obj.AEvent -= Myhandler 被调用");
Obj.AEvent -= MyHandler;
Console.WriteLine();
//再次试图激发事件
Console.WriteLine("Main函数试图在撤消事件后激发Obj的AEvent事件!");
Obj.FireAEvent();
Console.WriteLine("---程序运行完毕!---");
Console.ReadLine();
}
//真正的事件处理函数
static void MyEventHandler()
{
Console.WriteLine("This is a Event!");
}
}
}
运行,我们从程序的输出结果中可以看出,当我们在Main函数中调用
Obj.FireAEvent();
方法后,我们的MyEventHandler事件处理函数被调用,屏幕输出 “This is a Event!”。
下面我们结合该Console程序的输出结果分析一下这个MyEventHandler是如何被调用的:
――――――――――――――――――――――――――――
(1)MyHandler的HashCode为:10048139
(2)Obj.AEvent += Myhandler 被调用
(3)AEvent add 被调用,value的HashCode为:10048139
(4)Main函数激发Obj的AEvent事件!
(5)This is a Event!
(6)Obj.AEvent -= Myhandler 被调用
(7)AEvent remove 被调用,value的HashCode为:10048139
(8)Main函数试图在撤消事件后激发Obj的AEvent事件!
---程序运行完毕!---
――――――――――――――――――――――――――――
首先,Obj.AEvent += Myhandler被调用后,MyHandler被作为隐含的value参数传递给MyClass中的事件AEvent的add访问器,我们在该访问器中设置m_Handler成员变量为传递过来的value(通过HashCode我们可以知道该参数和Main函数中的MyHandler为同一对象)即我们的MyHandler(该代理实际上指向我们的MyEventHandler函数),当Main函数调用Obj.FireEvent()时,Obj的m_Handler被调用,也就是我们的MyEventHandler被调用。
Obj.AEvent -= Myhandler被调用时,AEvent的remove访问器被调用,我们在这里置m_Handler为null,撤消该事件,Main函数再次FireEvent时,由于Obj的m_Handler为null,所以直接返回到Main函数中,事件处理函数不再被调用。
通过这个简单的例子,我们可以从整体上了解C#的Event机制的一般用法和浅层原理(深层的原理我还没有弄明白^_^)。可以看到,在C#中事件机制是在语言级通过“函数代理(delegate)”和“event”关键字被直接支持的,而在C++等语言中是必须自己写代码实现的。
打开VS.NET,新建一个C# Console Application,执行“项目”->“添加类”菜单功能,添加一个“MyClass”类:
using System;
namespace ConsoleApplication1
{
//声明一个delegate
public delegate void EventHandler();
/// ///测试C#的event机制。
/// public class MyClass
{
//声明一个成员变量来保存事件句柄(事件被激发时被调用的delegate)
private EventHandler m_Handler = null;
//激发事件
public void FireAEvent()
{
if(m_Handler != null)
{
m_Handler();
}
}
//声明事件
public event EventHandler AEvent
{
add//添加访问器
{
//注意,访问器中实际包含了一个名为value的隐含参数
//该参数的值即为客户程序调用+=时传递过来的delegate
Console.WriteLine("AEvent add 被调用,value的HashCode为:" + value.GetHashCode());
if(value != null){m_Handler = value;};//设置m_Handler域保存新的handler
}
remove//删除访问器
{
Console.WriteLine("AEvent remove 被调用,value的HashCode为:" + value.GetHashCode());
if(value == m_Handler){m_Handler = null;}//置m_Handler为null,该事件将不再被激发
}
}
public MyClass()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
}
}
然后在主文件Class1.cs中输入如下代码:
using System;
namespace ConsoleApplication1
{
/// /// Class1 的摘要说明。
/// class Class1
{
/// ///应用程序的主入口点。
/// [STAThread]
static void Main(string[] args)
{
//
// TODO: 在此处添加代码以启动应用程序
//
//实例化一个MyClass的对象Obj
MyClass Obj = new MyClass();
//基于MyEventHandler()函数定义一个EventHandler
EventHandler MyHandler = new EventHandler(MyEventHandler);
Console.WriteLine("MyHandler的HashCode为:"+MyHandler.GetHashCode());
Console.WriteLine();
//预定事件
Console.WriteLine("Obj.AEvent += Myhandler 被调用");
Obj.AEvent += MyHandler;
//激发事件
Console.WriteLine("Main函数激发Obj的AEvent事件!");
Obj.FireAEvent();
//撤消事件
Console.WriteLine("Obj.AEvent -= Myhandler 被调用");
Obj.AEvent -= MyHandler;
Console.WriteLine();
//再次试图激发事件
Console.WriteLine("Main函数试图在撤消事件后激发Obj的AEvent事件!");
Obj.FireAEvent();
Console.WriteLine("---程序运行完毕!---");
Console.ReadLine();
}
//真正的事件处理函数
static void MyEventHandler()
{
Console.WriteLine("This is a Event!");
}
}
}
运行,我们从程序的输出结果中可以看出,当我们在Main函数中调用
Obj.FireAEvent();
方法后,我们的MyEventHandler事件处理函数被调用,屏幕输出 “This is a Event!”。
下面我们结合该Console程序的输出结果分析一下这个MyEventHandler是如何被调用的:
――――――――――――――――――――――――――――
(1)MyHandler的HashCode为:10048139
(2)Obj.AEvent += Myhandler 被调用
(3)AEvent add 被调用,value的HashCode为:10048139
(4)Main函数激发Obj的AEvent事件!
(5)This is a Event!
(6)Obj.AEvent -= Myhandler 被调用
(7)AEvent remove 被调用,value的HashCode为:10048139
(8)Main函数试图在撤消事件后激发Obj的AEvent事件!
---程序运行完毕!---
――――――――――――――――――――――――――――
首先,Obj.AEvent += Myhandler被调用后,MyHandler被作为隐含的value参数传递给MyClass中的事件AEvent的add访问器,我们在该访问器中设置m_Handler成员变量为传递过来的value(通过HashCode我们可以知道该参数和Main函数中的MyHandler为同一对象)即我们的MyHandler(该代理实际上指向我们的MyEventHandler函数),当Main函数调用Obj.FireEvent()时,Obj的m_Handler被调用,也就是我们的MyEventHandler被调用。
Obj.AEvent -= Myhandler被调用时,AEvent的remove访问器被调用,我们在这里置m_Handler为null,撤消该事件,Main函数再次FireEvent时,由于Obj的m_Handler为null,所以直接返回到Main函数中,事件处理函数不再被调用。
通过这个简单的例子,我们可以从整体上了解C#的Event机制的一般用法和浅层原理(深层的原理我还没有弄明白^_^)。可以看到,在C#中事件机制是在语言级通过“函数代理(delegate)”和“event”关键字被直接支持的,而在C++等语言中是必须自己写代码实现的。
相关文章推荐
- C++ 事件机制实现(转载自http://blog.csdn.net/khler/archive/2007/08/07/1729638.aspx)
- Windows消息机制http://blog.csdn.net/weixu_2008/archive/2007/09/15/1785939.aspx
- [转]C#数据库连接字符串 [http://blog.csdn.net/xiaokexinger/archive/2007/03/26/1541441.aspx]
- 在C#中使用异步Socket编程实现TCP网络服务的C/S的通讯构架(一)----基础类库部分(来源:http://blog.csdn.net/yangjundeng/archive/2005/03/17/321920.aspx)
- c#读取并修改App.config文件实例(转载:http://blog.csdn.net/abuhome/archive/2010/01/13/5184467.aspx)
- C#写的程序集注册成标准的Com组件,在asp中用Server.CreateObject()调用。 http://blog.csdn.net/lgq_12345/archive/2007/05/24/1624822.aspx
- C#向Excel报表中插入图片的2种方法 http://blog.csdn.net/net_lover/archive/2007/07/23/1702797.aspx
- 新版公农历转换类(C#) 转自http://blog.csdn.net/BlueDog/archive/2006/12/13/1440594.aspx
- C#环境下的钩子详解(转自http://blog.csdn.net/stevenson_aspdotnet/archive/2010/03/04/5346725.aspx)
- 完整的CSS工具列表 http://blog.csdn.net/jaketseng/archive/2007/11/12/1880344.aspx
- http://blog.csdn.net/metababy/archive/2006/02/28/612102.aspx
- http://blog.csdn.net/ramacess/archive/2009/11/15/4812012.aspx
- 35 岁前程序员要规划好的四件事[转自:http://blog.csdn.net/oiio/archive/2007/02/12/1508001.aspx]
- 40 个轻量级 JavaScript 库 (转自:http://blog.csdn.net/comsharp/archive/2009/03/05/3959377.aspx)
- struts2 标签 s (转http://blog.csdn.net/yanyuening/archive/2009/06/06/4246995.aspx)
- js 经典收集 http://blog.csdn.net/fanweiwei/archive/2007/04/06/1553712.aspx
- Windows内存机制解析(http://blog.csdn.net/leezy_2000)
- 内部排序算法 http://blog.csdn.net/nixun/archive/2005/10/04/495186.aspx
- http://blog.csdn.net/wingfeng19800215/archive/2007/02/27/1515925.aspx
- http://blog.csdn.net/xjbx/archive/2009/04/20/4093403.aspxVisual Studio 2008 每日提示